在打开推送通知时解析推送“未找到活动”

Posted

技术标签:

【中文标题】在打开推送通知时解析推送“未找到活动”【英文标题】:Parse Push "No Activity Found" on opening Push Notification 【发布时间】:2014-10-13 05:35:25 【问题描述】:

我使用Parse 作为后端制作了一个应用程序。我能够收到通知,但是当我点击它时,应用程序崩溃了。

这里是 java 和 XML 文件。

androidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="chipset.lugmnotifier">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <permission
        android:name="chipset.lugmnotifier.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="chipset.lugmnotifier.permission.C2D_MESSAGE" />

    <application
        android:name=".resources.ParseInitApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="com.parse.push.notification_icon"
            android:resource="@drawable/ic_notification" />

        <activity
            android:name=".HomeActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".AdminActivity"
            android:label="@string/title_activity_admin"
            android:parentActivityName=".HomeActivity">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".HomeActivity" />
        </activity>

        <service android:name="com.parse.PushService" />

        <receiver android:name="com.parse.ParseBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.USER_PRESENT" />
            </intent-filter>
        </receiver>
        <receiver
            android:name="com.parse.ParsePushBroadcastReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="com.parse.push.intent.RECEIVE" />
                <action android:name="com.parse.push.intent.DELETE" />
                <action android:name="com.parse.push.intent.OPEN" />
            </intent-filter>
        </receiver>
        <receiver
            android:name="com.parse.GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />


                <category android:name="chipset.lugmnotifier" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

ParseInitApplication.java

import android.app.Application;
import android.util.Log;

import com.parse.Parse;
import com.parse.ParseException;
import com.parse.ParseInstallation;
import com.parse.ParsePush;
import com.parse.SaveCallback;

import static chipset.lugmnotifier.resources.Constants.APPLICATION_ID;
import static chipset.lugmnotifier.resources.Constants.CLIENT_KEY;

public class ParseInitApplication extends Application 

    @Override
    public void onCreate() 
        super.onCreate();
        Parse.initialize(this, APPLICATION_ID, CLIENT_KEY);
        ParsePush.subscribeInBackground("", new SaveCallback() 
            @Override
            public void done(ParseException e) 
                if (e != null) 
                    Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
                 else 
                    Log.e("com.parse.push", "failed to subscribe for push", e);
                
            
        );
        ParseInstallation.getCurrentInstallation().saveInBackground();
    


HomeActivity.java

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.method.PasswordTransformationMethod;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;

import com.parse.FindCallback;
import com.parse.ParseAnalytics;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;

import org.duncavage.swipetorefresh.widget.SwipeRefreshLayout;

import java.util.List;

import chipset.lugmnotifier.resources.Functions;
import chipset.lugmnotifier.resources.NotificationListViewAdapter;
import de.keyboardsurfer.android.widget.crouton.Crouton;
import de.keyboardsurfer.android.widget.crouton.Style;

import static chipset.lugmnotifier.resources.Constants.KEY_CLASS_NOTIFICATION;
import static chipset.lugmnotifier.resources.Constants.KEY_DETAIL;
import static chipset.lugmnotifier.resources.Constants.KEY_TITLE;
import static chipset.lugmnotifier.resources.Constants.PASSWORD;

public class HomeActivity extends Activity 


    ListView notificationsListView;
    SwipeRefreshLayout notificationSwipeRefreshLayout;
    Functions functions = new Functions();

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        ParseAnalytics.trackAppOpened(getIntent());
        notificationSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.notificationSwipeRefreshLayout);
        notificationsListView = (ListView) findViewById(R.id.notificationListView);
        notificationSwipeRefreshLayout.setColorScheme(R.color.alizarin, R.color.emerald, R.color.peterRiver, R.color.sunFlower);
        notificationSwipeRefreshLayout.setActionBarSwipeIndicatorText(R.string.swipe_to_refresh);
        notificationSwipeRefreshLayout.setActionBarSwipeIndicatorRefreshingText(R.string.loading);
        notificationSwipeRefreshLayout.setActionBarSwipeIndicatorBackgroundColor(
                getResources().getColor(R.color.alizarin));
        notificationSwipeRefreshLayout.setActionBarSwipeIndicatorTextColor(
                getResources().getColor(R.color.clouds));
        notificationSwipeRefreshLayout.setActionBarSwipeIndicatorRefreshingTextColor(
                getResources().getColor(R.color.clouds));
        notificationSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() 
            @Override
            public void onRefresh() 
                new FetchData().getNotifications();
            
        );
        new FetchData().getNotifications();


    

    private class FetchData 

        public void getNotifications() 
            if (functions.isConnected(getApplicationContext())) 
                notificationSwipeRefreshLayout.setRefreshing(true);
                ParseQuery<ParseObject> query = ParseQuery.getQuery(KEY_CLASS_NOTIFICATION);
                query.findInBackground(new FindCallback<ParseObject>() 
                    @Override
                    public void done(List<ParseObject> parseObjects, ParseException e) 
                        notificationSwipeRefreshLayout.setRefreshing(false);
                        final String[] title = new String[parseObjects.size()];
                        final String[] detail = new String[parseObjects.size()];
                        if (e == null) 
                            for (int i = 0; i < parseObjects.size(); i++) 
                                title[i] = parseObjects.get(i).getString(KEY_TITLE);
                                detail[i] = parseObjects.get(i).getString(KEY_DETAIL);
                            
                            notificationsListView.setAdapter(new NotificationListViewAdapter(getApplicationContext(), title, detail));
                            notificationsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
                                @Override
                                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
                                    Crouton.showText(HomeActivity.this, title[i] + " - " + detail[i], Style.INFO);
                                
                            );
                         else 
                            Crouton.showText(HomeActivity.this, e.getMessage(), Style.ALERT);
                        
                    
                );
             else 
                notificationSwipeRefreshLayout.setRefreshing(false);
                Crouton.showText(HomeActivity.this, "No internet connection", Style.ALERT);
            
        
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.

        getMenuInflater().inflate(R.menu.menu, menu);
        return true;

    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_admin) 
            final EditText passwordEditText = new EditText(HomeActivity.this);
            passwordEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
            AlertDialog.Builder builder = new AlertDialog.Builder(HomeActivity.this);
            builder.setTitle("Admin Panel");
            builder.setMessage("Enter the admin password");
            builder.setView(passwordEditText);
            builder.setPositiveButton("LOGIN", new DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialogInterface, int i) 
                    if (passwordEditText.getText().toString().equals(PASSWORD)) 
                        startActivity(new Intent(HomeActivity.this, AdminActivity.class));
                     else 
                        Crouton.showText(HomeActivity.this, "Incorrect Password", Style.ALERT);
                    
                
            );
            builder.setNeutralButton("CANCEL", null);
            builder.create();
            builder.show();
        
        return super.onOptionsItemSelected(item);
    

StackTrace(崩溃)

10:46:02.302  15739-15739/chipset.lugmnotifier E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: chipset.lugmnotifier, PID: 15739
    java.lang.RuntimeException: Unable to start receiver com.parse.ParsePushBroadcastReceiver: android.content.ActivityNotFoundException: No Activity found to handle Intent  act=android.intent.action.VIEW dat= flg=0x1000c000 (has extras) 
            at android.app.ActivityThread.handleReceiver(ActivityThread.java:2414)
            at android.app.ActivityThread.access$1700(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1272)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: android.content.ActivityNotFoundException: No Activity found to handle Intent  act=android.intent.action.VIEW dat= flg=0x1000c000 (has extras) 
            at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1632)
            at android.app.Instrumentation.execStartActivitiesAsUser(Instrumentation.java:1481)
            at android.app.ContextImpl.startActivitiesAsUser(ContextImpl.java:1080)
            at android.content.ContextWrapper.startActivitiesAsUser(ContextWrapper.java:344)
            at android.content.ContextWrapper.startActivitiesAsUser(ContextWrapper.java:344)
            at android.app.TaskStackBuilder.startActivities(TaskStackBuilder.java:221)
            at android.app.TaskStackBuilder.startActivities(TaskStackBuilder.java:232)
            at android.app.TaskStackBuilder.startActivities(TaskStackBuilder.java:208)
            at com.parse.TaskStackBuilderHelper.startActivities(TaskStackBuilderHelper.java:19)
            at com.parse.ParsePushBroadcastReceiver.onPushOpen(ParsePushBroadcastReceiver.java:202)
            at com.parse.ParsePushBroadcastReceiver.onReceive(ParsePushBroadcastReceiver.java:108)
            at android.app.ActivityThread.handleReceiver(ActivityThread.java:2407)
            at android.app.ActivityThread.access$1700(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1272)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

我想在点击通知时打开 HomeActivity。任何帮助将不胜感激。如果需要任何其他文件,请告诉我,我会添加它。

【问题讨论】:

【参考方案1】:

引用 Ahmad Raza 的以下帖子 Exception when opening Parse push notification

您可以扩展 ParsePushBroadcastReceiver 并覆盖 onPushOpen 方法。

public class Receiver extends ParsePushBroadcastReceiver 

    @Override
    public void onPushOpen(Context context, Intent intent) 
        Log.e("Push", "Clicked");
        Intent i = new Intent(context, HomeActivity.class);
        i.putExtras(intent.getExtras());
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    

在清单中使用它,(而不是使用 ParsePushBroadcastReceiver)

<receiver
        android:name="your.package.name.Receiver"
        android:exported="false" >
    <intent-filter>
        <action android:name="com.parse.push.intent.RECEIVE" />
        <action android:name="com.parse.push.intent.DELETE" />
        <action android:name="com.parse.push.intent.OPEN" />
    </intent-filter>
</receiver>

【讨论】:

你是如何让 onPushOpen 工作的?有什么特别的,因为正如你所写的,这对我不起作用。【参考方案2】:

经过长时间的努力,它对我有用:

ParsePushApplication.java

public class ParsePushApplication extends Application 
@Override
public void onCreate()
    super.onCreate();
    Parse.initialize(this, "App_Key", "Client_Key");
    ParseInstallation.getCurrentInstallation().saveInBackground();
   

MainActivity.java

public class MainActivity extends AppCompatActivity 

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ParseAnalytics.trackAppOpenedInBackground(getIntent());
    try 
        Intent intent = getIntent();
        Bundle extras = intent.getExtras();
        if (extras != null) 
            String jsonData = extras.getString("com.parse.Data");
            JSONObject json;
            json = new JSONObject(jsonData);
            String pushStore = json.getString("alert");
            Toast.makeText(MainActivity.this, pushStore, Toast.LENGTH_LONG).show();
     catch (JSONException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

Receiver.java

public class Receiver extends ParsePushBroadcastReceiver 

private static final String TAG = "MyNotificationsReceiver";

@Override
public void onPushOpen(Context context, Intent intent) 
    Log.e("Push", "Clicked");
    Intent i = new Intent(context, MainActivity.class);
    i.putExtras(intent.getExtras());
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(i);
    

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package.name">

<!-- IMPORTANT: Change "your.package.name" to match your app's package name. -->

<application
    android:name=".ParsePushApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <meta-data
        android:name="com.parse.push.notification_icon"
        android:resource="@drawable/push_icon"/>

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    </activity>
    <service android:name="com.parse.PushService" />

    <receiver android:name="com.parse.ParseBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.USER_PRESENT" />
        </intent-filter>
    </receiver>
    <receiver
        android:name="your.package.name.Receiver"
        android:exported="false" >
        <intent-filter>
            <action android:name="com.parse.push.intent.RECEIVE" />
            <action android:name="com.parse.push.intent.DELETE" />
            <action android:name="com.parse.push.intent.OPEN" />
        </intent-filter>
    </receiver>

    <receiver android:name="com.parse.GcmBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

            <!--
              IMPORTANT: Change "your.package.name" to match your app's package name.
            -->
            <category android:name="your.package.name" />
        </intent-filter>
    </receiver>

</application>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<!--
  IMPORTANT: Change "your.package.name.permission.C2D_MESSAGE" in the lines below
  to match your app's package name + ".permission.C2D_MESSAGE".
-->
<permission android:protectionLevel="signature"
    android:name="your.package.name.permission.C2D_MESSAGE" />
<uses-permission android:name="com.zeeroapps.parsetutorial_cli.permission.C2D_MESSAGE" />

</manifest>

【讨论】:

以上是关于在打开推送通知时解析推送“未找到活动”的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 中处理解析推送通知

反正有保存推送通知吗?

解析 PFAnalytics 不跟踪推送打开

Android - 解析推送通知在打开时崩溃

单击推送通知时如何打开活动?

如何在点击推送通知时打开特定帖子