一、前言
今天我们来看一下Android中一个众人熟悉的一个属性:shareUserId,关于这个属性可能大家都很熟悉了,最近在开发项目,用到了这个属性,虽然知道一点知识,但是感觉还是有些迷糊,所以就写篇文章来深入研究一下。
关于Android中的sharedUserId的概念这里就简单介绍一下:
Android给每个APK进程分配一个单独的空间,manifest中的userid就是对应一个分配的Linux用户ID,并且为它创建一个沙箱,以防止影
响其他应用程序(或者其他应用程序影响它)。用户ID 在应用程序安装到设备中时被分配,并且在这个设备中保持它的永久性。
通常,不同的APK会具有不同的userId,因此运行时属于不同的进程中,而不同进程中的资源是不共享的,在保障了程序运行的稳定。然后在有些时候,我们自己开发了多个APK并且需要他们之间互相共享资源,那么就需要通过设置shareUserId来实现这一目的。
通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中.所以默认就是可以互相访问任意数据. 也可以配置成运行成不同的进程, 同时可以访问其他APK的数据目录下的数据库和文件.就像访问本程序的数据一样。
用法也很简单:
在需要共享资源的项目的每个AndroidMainfest.xml中添加shareuserId的标签。
android:sharedUserId="com.example"
id名自由设置,但必须保证每个项目都使用了相同的sharedUserId。一个mainfest只能有一个Shareuserid标签。
二、问题延伸
我们今天先来看一个场景:Android中一个App如何能够访问到其他App的信息和资源?
这个可能很多人感觉是两个App之间的通信,其实不是,比如我们在早期遇到支付宝有一个快捷支付,那么我们会看到手机中会安装两个app,一个是支付宝app,一个是快捷支付app,那么在开启快捷支付的时候,就会调用快捷支付app等,大家可能会想到现在有一个比较流行的技术叫做插件开发,的确如此,这个我在之前的文章也有说过,不清楚的同学可以点击这里:Android中插件开发篇
但是我们今天不说这个插件怎么搞,今天就来看看如何在一个app中去访问另外一个app的代码和资源等信息?
在说这个知识点之前,我们需要了解的一个知识点,就是我们可以通过一个包名来得到对应的Context的全局变量,可以直接使用Context的一个静态方法:createPackageContext
关于这个方法其实很简单,他有两个参数:
第一个参数:需要构造出来Context的包名字符串
第二个参数:构造出来的Context的开启模式
下面我们可以直接使用一个例子来看看效果:
首先我们弄一个插件工程:ShareUserIdPlugin
这个工程很简单,我们编译安装运行即可。
在弄一个宿主工程:ShareUserIdHost
这里有一个核心方法,我们首先通过插件工程的包名:cn.wjdiankong.shareuseridplugin;创建出一个Context对象。
这里看到第二参数有两个模式:
Context.CONTEXT_INCLUDE_CODE:这个标志是在我们需要执行插件中的某段代码需要加上的值。
CONTEXT_IGNORE_SECURITY:这个标志是必须的,是忽视安全性,如果没有这个值的话,那么我们访问什么都是失败的。
得到了Context变量之后,我们下面就可以通过反射来执行代码和获取资源了,这里需要注意的是,一定要先拿到Context对应的ClassLoader,然后才能加载对应的类,ClassLoader一定是Context的,是插件工程中的类加载器。
下面我们运行结果看看:
运行成功了啦~~是不是很简单呢。
下面如果我们把CONTEXT_INCLUDE_CODE去掉,在运行:
发现报错了,找不到指定的类。所以如果想运行代码的话,这个值一定要加上。
我们再把CONTEXT_IGNORE_SECURITY去掉,运行结果:
看到了,爆出了安全错误,所以要想构造成功Context出来,必须要加上这个值。
三、步入正题
好了,到这里我们就介绍了如何通过包名构造一个Context变量出来,然后执行对应的代码和获取资源。那么这个我们看到工程中貌似没有用到shareUserId这个属性呢?那这个和我们今天要介绍的知识点有什么关系吗?其实没什么关系,