-
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。
或许有其他方法,待续。