-
public
class
ActivityGroupActivity
extends
ActivityGroup { @Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState); setContentView(R.layout.main); LocalActivityManager am
=
getLocalActivityManager(); FrameLayout layout
=
(FrameLayout) findViewById(R.layout.activity_layout);
//
本地进程Activity
Intent intent2
=
new
Intent(
this
, Sample2Activity.
class
); Window window2
=
am.startActivity(
"
Sample2_UniqueString
"
, intent2); View view2
=
window2.getDecorView(); layout.addView(view2);
//
其他进程的Activity
Intent intent3
=
new
Intent(); intent3.setClassName(
"
com.example.plasma
"
,
"
com.example.plasma.Plasma
"
); Window window3
=
am.startActivity(
"
Sample3_UniqueString
"
, intent3); View view3
=
window3.getDecorView(); layout.addView(view3); } }
2. 本地进程的Activity可以启动,但是其他进程的Activity不能启动,启动其他进程Activity的logcat如下
02-10 11:34:23.690: DEBUG/ActivityGroup(1625): onCreate
02-10 11:34:23.700: DEBUG/ActivityGroup(1625): 1111
02-10 11:34:23.710: DEBUG/AndroidRuntime(1625): Shutting down VM
02-10 11:34:23.710: WARN/dalvikvm(1625): threadid=3: thread exiting with uncaught exception (group=0x4001b160)
02-10 11:34:23.710: ERROR/AndroidRuntime(1625): Uncaught handler: thread main exiting due to uncaught exception
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): java.lang.RuntimeException: Unable to start activity ComponentInfo
{org.jpn.techbooster.sample.activityGroupActivity/org.jpn.techbooster.sample.activityGroupActivity.ActivityGroupActivity}: java.lang.SecurityException:
Requesting code from com.example.plasma (with uid 10053) to be run in process org.jpn.techbooster.sample.activityGroupActivity (with uid 10052)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.os.Handler.dispatchMessage(Handler.java:99)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.os.Looper.loop(Looper.java:123)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.main(ActivityThread.java:4363)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at java.lang.reflect.Method.invokeNative(Native Method)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at java.lang.reflect.Method.invoke(Method.java:521)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at dalvik.system.NativeStart.main(Native Method)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): Caused by: java.lang.SecurityException: Requesting code from com.example.plasma (with uid 10053) to be run in
process org.jpn.techbooster.sample.activityGroupActivity (with uid 10052)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.getPackageInfo(ActivityThread.java:2154)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2390)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.startActivityNow(ActivityThread.java:2335)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.LocalActivityManager.moveToState(LocalActivityManager.java:127)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.LocalActivityManager.startActivity(LocalActivityManager.java:339)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at org.jpn.techbooster.sample.activityGroupActivity.ActivityGroupActivity.onCreate
(ActivityGroupActivity.java:54)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
02-10 11:34:23.730: ERROR/AndroidRuntime(1625): ... 11 more
3. Trace ActivityGroup
通过调查ActivityGroup的实现,发现是通过LocalActivityManager来管理"embedded activities",而且SDK文档明确说明仅支持同一进程的activities
LocalActivityManager Class Overview
Helper class for managing multiple running embedded activities
in the same process. This class is not normally used directly, but rather created for you as
part of the ActivityGroup implementation.
4. Trace LocalActivityManager
继续调查LocalActivityManager 的实现,发现这个类不过是管理embedded activities的一些信息而已。数据结构如下
-
Java code
-
//
Internal token for an Activity being managed by LocalActivityManager.
private
static
class
LocalActivityRecord
extends
Binder { LocalActivityRecord(String _id, Intent _intent) { id
=
_id; intent
=
_intent; }
final
String id;
//
Unique name of this record.
Intent intent;
//
Which activity to run here.
ActivityInfo activityInfo;
//
Package manager info about activity.
Activity activity;
//
Currently instantiated activity.
Window window;
//
Activity's top-level window.
Bundle instanceState;
//
Last retrieved freeze state.
int
curState
=
RESTORED;
//
Current state the activity is in.
}
/**
id -> record of all known activities.
*/
private
final
Map
<
String, LocalActivityRecord
>
mActivities
=
new
HashMap
<
String, LocalActivityRecord
>
();
/**
array of all known activities for easy iterating.
*/
private
final
ArrayList
<
LocalActivityRecord
>
mActivityArray
=
new
ArrayList
<
LocalActivityRecord
>
();
5. 问题
(1) embedded activities和普通的activity有什么不同,为什么可以多个同时运行。一般来讲只有栈顶的activity才是运行状态,被压盖的都是paused或者stoped状态。
(2) 为什么ActivityGroup不支持不同进程的Activity,原因是什么。
恭请各位高人相助。谢谢!
方法:
1、在activityThread.java的代码里添加对安全忽略即可。
r.packageInfo = getPackageInfo(aInfo.applicationInfo,
Context.CONTEXT_INCLUDE_CODE + Context.CONTEXT_IGNORE_SECURITY);
2、<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:sharedUserId="com.android.activitygrouptest"
android:versionName="1.0">
设定sharedUserId一致就可以了,这样两个apk会加载到同一个process中运行,同时要把你要启动的activity launchemode 设定为singletop。
或许有其他方法,待续。