两个具有相同名称的Android应用程序进程,为什么?

时间:2014-08-28 14:30:24

标签: android

Android设备是否有任何理由可以启动具有相同名称,相同用户ID和不同PID的应用程序的新流程,并保持旧设备仍处于活动状态?

清单未指定除默认进程以外的任何其他进程。

旧进程可以通过终端中的kill命令终止。

在某些已定义的情况下,这是预期的行为还是Android错误?

清单看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mycompany.myapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="19" />

    <!-- omitted <uses-permission> tags -->

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >

        <!-- Start up -->
        <activity
            android:name=".activity.SplashScreenActivity"
            android:configChanges="orientation|keyboardHidden" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- other non-launcher activities... -->

        <!-- Auto start on boot -->
        <receiver android:name=".receiver.StartEventsReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

        <!-- Update content and configuration -->
        <receiver
            android:name=".receiver.UpdateContentReceiver"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.mycompany.myapp.UPDATE_CONTENT" />
                <action android:name="com.mycompany.myapp.CONTENT_UPDATED" />
            </intent-filter>
        </receiver>
        <!-- other receivers and services... -->

    </application>

</manifest>

更新:我设法获得了一些日志记录。我的应用程序有一个名为UpdateContentReceiver的Receiver(上面更新的清单),每隔一分钟调用一次UPDATE_CONTENT意图,从主消息队列发布。它进行一些网络轮询和完成。它曾经工作......

08-30 09:46:57.419  2512  2512 V UpdateContentReceiver: Received UPDATE_CONTENT
08-30 09:46:58.349  2512  2512 V UpdateContentReceiver: No update

08-30 09:47:57.439  2512  2512 V UpdateContentReceiver: Received UPDATE_CONTENT
08-30 09:47:57.739  2512  2512 V UpdateContentReceiver: No update

08-30 09:48:57.439  2512  2512 V UpdateContentReceiver: Received UPDATE_CONTENT
08-30 09:49:02.389  2512  2512 V UpdateContentReceiver: No update

......但下次......

08-30 09:49:57.459  1879  1904 E JavaBinder: !!! FAILED BINDER TRANSACTION !!!
08-30 09:49:57.469  1879  1904 W BroadcastQueue: Exception when sending broadcast to ComponentInfo{com.mycompany.myapp/com.mycompany.myapp.receiver.UpdateContentReceiver}
08-30 09:49:57.469  1879  1904 W BroadcastQueue: android.os.TransactionTooLargeException
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.os.BinderProxy.transact(Native Method)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.app.ApplicationThreadProxy.scheduleReceiver(ApplicationThreadNative.java:771)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.BroadcastQueue.processCurBroadcastLocked(BroadcastQueue.java:231)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:778)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.BroadcastQueue$1.handleMessage(BroadcastQueue.java:140)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.os.Handler.dispatchMessage(Handler.java:99)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at android.os.Looper.loop(Looper.java:137)
08-30 09:49:57.469  1879  1904 W BroadcastQueue:    at com.android.server.am.ActivityManagerService$AThread.run(ActivityManagerService.java:1487)
08-30 09:49:57.469  1879  1904 W ActivityManagerService: Scheduling restart of crashed service com.mycompany.myapp/.service.ServiceFoo in 5000ms
08-30 09:49:57.469  1879  1904 W ActivityManagerService: Scheduling restart of crashed service com.mycompany.myapp/.service.ServiceBar in 14999ms
08-30 09:49:57.469  1879  1904 W ActivityManagerServiceActivityStack_hong: Force removing ActivityRecord{42768bf8 u0 com.mycompany.myapp/.activity.MyActivity}: app died, no saved state
08-30 09:49:57.529  1879  1904 I ActivityManagerService: Start proc com.mycompany.myapp for broadcast com.mycompany.myapp/.receiver.UpdateContentReceiver: pid=27119 uid=10044 gids={50044, 3003, 1028, 1015, 1023}

最后一行清楚地表明创建了一个新流程。之后,我在日志中看到MyApplication使用不同的PID启动了三次,直到它与最后一个进程一起生效。这是ps|grep myapp输出:

u0_a44    2512  1286  755540 85548 ffffffff 4003fee4 S com.mycompany.myapp                                                                      
u0_a44    28541 1286  772220 79204 ffffffff 4003fee4 S com.mycompany.myapp

我不能说TransactionTooLargeException为什么会发生(我们只发送UPDATE_CONTENT没有额外内容,所以内存占用很少),但至少我知道为什么要创建一个新进程。仍然不清楚为什么旧的过程不会被破坏。该应用程序有一个内部Web服务器:也许Android看到侦听TCP端口并拒绝杀死它?

有趣的是,新进程无法运行自己的Web服务器(因为侦听端口已经绑定),但是一切都“有效”,因为旧的Web服务器仍然存在!

1 个答案:

答案 0 :(得分:0)

指的是:Re-launch of Activity on Home button, but...only the first time 或者:How to prevent multiple instances of an activity when it is launched with different intents

您可以将应用定义为:android:launchMode="singleInstance" 但我选择:

if (!isTaskRoot()) {
    final Intent intent = getIntent();
    final String intentAction = intent.getAction(); 
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
        Log.w(LOG_TAG, "Main Activity is not the root.  Finishing Main Activity instead of launching.");
        finish();
        return;       
    }
}

编辑:(等待问题中的清单)

  

<强>机器人:多进程   是否可以将活动的实例启动到启动它的组件的进程中 - 如果可以,则为“true”,否则为“false”。默认值为“false”。

     

通常,活动的新实例会启动到定义它的应用程序的进程中,因此所有实例都会被启动   活动在同一个过程中运行。但是,如果此标志设置为   “true”,活动的实例可以在多个进程中运行,   允许系统在任何地方创建实例   (提供权限允许),几乎从不   必要或可取的。

来源:https://developer.android.com/guide/topics/manifest/activity-element.html