应用程序异常行为未启动意图中提到的活动

5

该应用程序中有三个主要类

1)Intent服务:在此处,我接收推送通知并根据通知信息和其他两个类的行为打开活动。以下是执行此操作的代码:

 if(Global.isMainScreenRunning){
   Intent intent = new Intent(this, MainScreen.class);
   intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(intent);
} else if(!Global.NotificationScreenRunning){
   Intent intent = new Intent(this, NotificationScreen.class);
   intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(intent);
}

2) NotificationScreen:这是中介屏幕,如果应用程序未运行,则首先显示此屏幕,并且在单击此屏幕的“是”按钮时将打开 MainScreen 并完成此屏幕。

3) Main screen: 这是应用程序的主屏幕,显示地图。其核心行为是 menifest 文件中提到的 launchmode="singletask",这意味着如果此屏幕正在运行,则其全部数据将发送到 onNewIntent() 方法,而不是再次打开此屏幕。

现在流程中正在发生什么

步骤1:应用程序在后台运行并收到推送通知。条件满足,第二个条件成功,并发出通知屏幕意图

步骤2:在通知屏幕上,我单击 ye 按钮以移动到下一个主屏幕

步骤3:在主屏幕上,我处理此信息并执行任务或仅关闭应用程序

步骤4:再次接收到新的通知,由于应用程序未运行,因此进入第二个条件并启动通知屏幕的意图,但是这次没有启动通知屏幕,而是提供了其意图并启动了错误的主屏幕。

这是我面临的异常行为,即错误地启动了主屏幕而不是提供通知屏幕类的意图,这与 Android 的应用程序完全不同。

非常感谢任何遇到此类问题的人的帮助。

编辑

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

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.front" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:name="android.hardware.microphone" />

    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission android:name="com.example.app.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.example.app.permission.C2D_MESSAGE" />

    <supports-screens
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/android_app_icon"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".SplashScreen"
            android:configChanges="keyboardHidden|orientation"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <activity
            android:name=".MainScreen"
            android:configChanges="keyboardHidden|orientation"
            android:launchMode="singleTask"
            android:excludeFromRecents="true"
            android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name=".NotificationScreen"
            android:configChanges="keyboardHidden|orientation"
            android:excludeFromRecents="true"
            android:screenOrientation="portrait" >
        </activity>

        <receiver
            android:name=".pushnotification.GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="com.selebrety.app" />
            </intent-filter>
        </receiver>

        <service android:name=".pushnotification.GcmIntentService" />

        <meta-data android:name="com.google.android.gms.version"
           android:value="@integer/google_play_services_version" />
    </application>

</manifest>

第二次编辑

我正在测试的手机是"YU Yureka",这里是它的规格链接。目前它有android 5.0.2操作系统。

第三次编辑

为了测试这个行为,我从eclipse调试器中调试了代码。为了检查这个问题,我在NotificationScreenonResumeonCreate中设置了断点,但是它们从未被命中,而是命中了MainScreenonResume

我还在if和else条件中添加了日志,但仍会输出else条件的日志。

第四次编辑 Global.isMainScreenRunning: 是一个全局的布尔变量,在MainScreenonPause中设为false,在MainScreenonResume中设为true。

Global.NotificationScreenRunning: 是一个全局的布尔变量,在NotificationScreenonPause中设为false,在NotificationScreenonResume中设为true。


@AbhinavSinghMaurya 我知道你说的是正在发生的事情,但根据提供的信息,这很可能不是正在发生的事情。你是如何测试的?你是否尝试在那个 if 块中放置一个日志消息? - Kevin Krumwiede
startActivity(Intent); - 那不可能是对的,应该是 startActivity(intent); 吧? - Kevin Krumwiede
Global.isMainScreenRunning在MainScreen的onResume中为true,在MainScreen的onPause中被设置为false。 - Abhinav Singh Maurya
让我们在聊天中继续这个讨论 - Abhinav Singh Maurya
尝试从“NotificationActivity”中删除“excludeFromRecents”,然后再试一试,这样行吗? - Darpan
显示剩余8条评论
5个回答

0

全局状态是有害的,这个问题就是证明。要理解发生了什么,您必须查看设置或清除全局标志的每个位置,并分析可能导致那里的所有可能执行路径。这远远超出了您可以在SO上获得的帮助范围。在Android上还有一个额外的复杂性,因为整个VM可能会被销毁(并清除所有全局变量),任何时候您的应用程序处于后台。同样糟糕的是,VM和Application实例可能会在退出最后一个活动后保留。当发生这种情况时,下次启动应用程序时将不再调用Application#onCreate(...),并且所有静态全局变量仍将设置为您上次运行应用程序时的值。

节省自己很多抓头发的时间,停止使用全局状态。


我相信你没有正确地阅读问题。请阅读问题并告诉我答案。顺便说一句,问题不在于全局变量,而是在于意图未能正确启动活动。 - Abhinav Singh Maurya
1
@AbhinavSinghMaurya 相信您没有正确阅读答案。 您的问题在没有分析整个应用程序中 Global.isMainScreenRunningGlobal.NotificationScreenRunning 的每次读取或写入情况的情况下是无法回答的。 - Kevin Krumwiede

0
你可以尝试在manifest文件中的MainScreen活动中添加android:taskAffinity=":main"
可能是因为MainScreen仍然与NotificationScreen在同一个任务中,所以当再次调用NotificationScreen时,它会调用所有任务。
你可以尝试这个演示来获得更多的视觉效果:play appcode
希望能有所帮助。

0

根据您的意思,您想在应用程序中收到通知时每次恢复通知屏幕。为此,我可以建议一种解决方案,这将使应用程序运行并允许您实现预期的行为,但是当您按下主屏幕按钮时,您的主屏幕将不再处于活动状态。它将被杀死。正如我们所知,Android为所有活动维护活动堆栈。因此,如果您按设备返回按钮,则活动将从堆栈中弹出,您将不会遇到此问题。

我认为这是活动堆栈的标准行为,有关更多信息,您可以使用此链接:

http://www.slideshare.net/RanNachmany/manipulating-android-tasks-and-back-stack

你可以尝试这段代码片段:
Intent i = new Intent(NotificationFullScreen.this,
      MainActivity.class);
    i.putExtra("FROM", "Notification");
    i.putExtra("bookingId", bookingId);
    i.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY
      | Intent.FLAG_FROM_BACKGROUND);
    startActivity(i);
    NotificationFullScreen.this.finish();

Ran Nachmany的演示非常棒。我之前不知道演示中提到的行为,从91-101页详细解释了我遇到的Intent.FLAG_ACTIVITY_NEW_TASK的确切行为。感谢您的回复。我用您提到的标志解决了问题。但是,离开MainScreen后我的屏幕将被关闭,如何处理默认行为呢?您的答案解决了我的问题。 - Abhinav Singh Maurya

-1

嗨@Abhinbav Singh Maurya

我认为问题在于主屏幕是从你在清单中声明为应用程序启动屏幕的闪屏屏幕中调用的,因此当应用程序被杀死并且你调用意图时,它将被调用。

相反,你可以将消息广播到闪屏屏幕,并在闪屏屏幕中接收它,并根据条件从那里调用意图。

再次提醒,你必须在SplahScreen中注册接收器后才能广播意图,否则它将永远不会被接收。因此,请尝试使用handler.postDelayed方法,在1000毫秒或700毫秒后广播。

 Intent mIntent = new Intent(context, SplashScreen.class);
                mIntent.setAction(Intent.ACTION_MAIN);
                mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
                mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(mIntent);
broadcastMessage(context, message);

我在下面的帖子中回答了类似的问题。 这里

我认为这就是你要找的。如果你觉得我的回答有用,请告诉我是否满足你的要求,如果我的回答对你有所帮助,请点赞以便让其他人也看到。

祝好:)

编辑

我已经对此进行了一些研究。

根据这个链接,你可以拥有两个启动器活动。

尝试一下并让我知道结果。希望能帮到你。:)


请仔细检查我的问题,我没有将mainscreen作为启动屏幕,我已将其启动模式声明为single task。它们之间有很大的区别。 - Abhinav Singh Maurya
你能在这里发布你的清单吗?在你的问题中,你提到MainScreen是应用程序的主屏幕。那么,为什么要对答案投反对票呢? - Programming Pirate
现在,当应用程序未运行且您尝试调用意图时,根据我的了解,您的“启动屏幕”将被加载。因此,显然您的启动屏幕将启动并加载您的“主屏幕”。因此,您需要从Intent服务中广播意图,并在启动屏幕中接收它,然后根据需要采取下一步操作。这就是我的答案所说的。我假设您的MainScreen是您的启动屏幕,请尝试并告诉我结果。 - Programming Pirate
请问为什么如果我提供通知屏幕的类给意图服务,启动画面会打开?是否有规定只能从意图服务打开启动器屏幕而不是普通屏幕? - Abhinav Singh Maurya
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/83015/discussion-between-abhinav-singh-maurya-and-sravan。 - Abhinav Singh Maurya
显示剩余3条评论

-2
if(Global.isMainScreenRunning){
   Intent intent = new Intent(this, MainScreen.class);
   intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(Intent);//here is the problem change Intent to intent 

} else if(!Global.NotificationScreenRunning){
   Intent intent = new Intent(this, NotificationScreen.class);
   intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(intent);
}

那不是我的问题。请仔细阅读问题并按照我在那里提到的步骤操作。 - Abhinav Singh Maurya
我认为你想表达的是,应用程序第一次正常运行,但当应用程序完成第一个周期后,它会表现异常。 - Padmakar Pandey
没错。就像在Eclipse中运行一个打开的应用程序而没有任何更改,它会说它的上一个任务被带到前面,我感觉这个应用程序也是这样的行为。 - Abhinav Singh Maurya
我检查了NotificationScreen的OnCreate和onResume条件,但都没有触发。 - Abhinav Singh Maurya
当推送通知在意图服务中接收到时,我会立即检查这些条件。我已经提供了流程和发生的情况。很抱歉我不能提供完整的源代码。 - Abhinav Singh Maurya
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接