项目要求:apk A 管理 3个其他的apk B,C,D. 要求这3个apk 不能在系统的luncher中显示应用图标,且只能被apk A 启动。
1. Activity 之间 传值,调用。如 apk A 一开启后就去 call apk B ,且等待 apk B 返回数据 ,再进行后续操作
第一步:A call B :在 apk A 启动后,只需在A的 onCreate() 函数中做如下操作
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.iptvsetting_activity); // A 的 布局文件
Intent mIntent = new Intent();
ComponentName cn = new ComponentName("com.iptv.usercheck","com.iptv.usercheck.UserCheckActivity"); // B的包名,B的 Activity 全称
mIntent.setComponent(cn);
startActivityForResult(intent, 100);
(1)因为这里是要等待 B 的返回值,所以用 startActivityForResult(Intent , int requestcode) 方法,若只是去call B 的话,可以用 startActivity(mIntent);
(2) 第二个参数 100 ,是用来, Call B 是由A 发起的 ,A给的暗号是 100,在后面代码中会用到
接着在 A 的 Activity 的 主程序中, 可以重写 返回值的 接收函数
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 100 && resultCode == 101)
{
if (data.getStringExtra("Result").equals("Exit") ){
finish();
}
}
}
在这个函数中 ,我们可以发现:
(1) 在 if 的判断条件中 出现了 requestCode == 100, 意识是先判断这个返回值来的是不是由我主动启动的 B apk 返回的, 而resultCode ,则是在 Call B 且B作出反应后,准备把 数据传递给 A 时 ,打上自己的标志,暗号为101,这样 就可以作出完整的判断,即 两者都相等的话,那么就是期待的数据了。
(2) data.getStringExtra("Result").equals("Exit") ;
data 这个对象, 正是 B 的 intent,在后面 B 的 Activity中传递过来。
"Result" 是B传递给A的数据的 标志,就好比是一个包裹,包裹里面装的才是数据 "Exit"
第二步 在 apk B 的 Activity 主程序中 做如下coding:
Intent intent = new Intent();
intent.putExtra("Result", "Exit");
setResult(101, intent);
finish();</span>
上述部分代码 就完成了 向 apk A 传递数据的操作,根据你业务逻辑,哪里需要此操作,就放置那里就okay.
setResult(resultCode, Intent) 函数,第一个参数 resultCODE= 101 ,和前面的requstCode = 100 对应,
第二个参数 intent 实例,把 apk B 的 intent 传递过去,
2. Apk 应用图标隐藏
Apk 在安装后,会在系统的luncher 中 显示一个应用图标,通过此图标,我们可以启动该apk. apk之所以在安装后会在luncher中显示图标,是在其 AndoridManifest.xml 文件中,对 其 Activity 做了属性配置,
<activity
android:name="com.iptv.iptvsetting.IPTVSettingActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> //其中这条配置就标识 此apk category 为 luncher ,所以会在 luncher 中显示图标
</intent-filter>
</activity></span>
apk 本身隐藏自己的图标:
去掉上面那条 category语句,或者将 android.intent.category.LAUNCHER 改为 android.intent.category.DEFAULT
上述操作涉及到apk 的源码修改,若要求不能修改源码,用其他的方式修改,如:由 apk A 去 隐藏 apk B ,C D,但 apk A 仍可以自由启动 B , C , D?
第一个问题:不修改B、C、D的源码,用apk A 去隐藏 B,C,D,
在 A 的Acitivy的 onCreate 中做如下操作:
PackageManager pm = getPackageManager();
pm.setApplicationEnabledSetting("B的包名", PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
但是执行此操作前,确保 apk A 的 Androidmanifest.xml 中一添加如下属性配置(1)&(2):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.iptv.iptvsetting"
android:versionCode="10041"
android:versionName="1.0.41.20140830"
android:sharedUserId="android.uid.system" >(1)
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE">(2)
而这样一来的话,通过编译生成的apk A 拥有了系统权限,只有在签名后才能在安卓机上才能安装。而签名工具是跟着安卓的版主走的,也就是安卓4.4.2 和4.4.4两个不用
的版本,签名工具是不同的,因而这是不建议此方法的原因之一
原因之二,就是 setApplicationEnabledSetting()的第二个参数, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,一旦为apk B 由 apk A 通过 setApplicationEnabledSetting() 函数 设置了此参数后,apk B 也就不能被 其他apk 启动了。我在设置->应用程序->下载,中查看到此时被修改后apk B 的状态为 未启动,虽然达到了 隐藏apk B 在luncher中应用图标的目的,但没有 实现第二个目的,apk A 能够自由的启动 apk B,C,D.
==========================================================================================================================
由于暂时还未找到完成符合项目目标的方法,所以还在调研中.......................