Parse Push “No Activity Found” on opening Push Not

2019-05-23 00:22发布

问题:

I made an app using Parse as backend. I am able to get the notification but when i tap on it, the app crashes.

Here are the java and XML files.

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 (of the crash)

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)

I want to open HomeActivity on notification tap. Any help will be appreciated. If any other file is required, please let me know I'll add it.

回答1:

Quoting from below post by Ahmad Raza Exception when opening Parse push notification

You can extend ParsePushBroadcastReceiver and override onPushOpen method.

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);
    }
}

Use it in manifest, (Instead of using 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>


回答2:

After a long effort, it worked for me:

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>