Receive Push Notifications into library project

2019-06-03 23:29发布

问题:

I have one project as a library to export to lite version of my project. In the library project, I have implemented push notifications. I've runthe library project as a normal project and the push notification work fine. My problem happens when i am importing this project as a library in lite version project.The push notification failed.

Here is my GCMIntentService class:

public class GCMIntentService extends GCMBaseIntentService {
    public static final String SENDER_ID = "206703456431";

    public GCMIntentService() {
        super(SENDER_ID);
    }

    private static final String TAG = "===GCMIntentService===";

    @Override
    protected void onRegistered(Context arg0, String registrationId) {
        Log.i(TAG, "Device registered: regId = " + registrationId);
        Applications app = (Applications) getApplication();
        app.setDeviceToken(registrationId);
    }

    @Override
    protected void onUnregistered(Context arg0, String arg1) {
        Log.i(TAG, "unregistered = " + arg1);
    }

    @Override
    protected void onMessage(Context arg0, Intent arg1) {
        Log.i(TAG, "Received message. Extras: " + arg1.getExtras());
        String message = arg1.getExtras().getString("message");
        displayMessage(arg0, message);
        // notifies user
        generateNotification(arg0, message);


    }

    @Override
    protected void onError(Context arg0, String errorId) {
        Log.i(TAG, "Received error: " + errorId);
    }

    @Override
    protected boolean onRecoverableError(Context context, String errorId) {
        return super.onRecoverableError(context, errorId);
    }

    /**
     * Issues a notification to inform the user that server has sent a message.
     */
    @SuppressWarnings("deprecation")
    private static void generateNotification(Context context, String message) {
        int icon = R.drawable.icon_57x57_fixed;
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = new Notification();
        notification.defaults |= Notification.DEFAULT_SOUND;
        notification.icon = icon;
        String title = context.getString(R.string.app_name);
        Intent notificationIntent = new Intent(context,
                HomeScreenActivity.class);
        Intent notificationIntentV2 = new Intent(context,
                LoginActivity.class);
        // set intent so it does not start a new activity

        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                    | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        notification.flags = Notification.FLAG_AUTO_CANCEL;

        PendingIntent intent = PendingIntent.getActivity(context, 0,
                    notificationIntent, 0);
        notification.setLatestEventInfo(context, title, message, intent);
        notificationManager.notify(0, notification);




    }

    class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Context... params) {
            final Context context = params[0].getApplicationContext();
            return isAppOnForeground(context);
        }

        private boolean isAppOnForeground(Context context) {
            ActivityManager activityManager = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            List<RunningAppProcessInfo> appProcesses = activityManager
                    .getRunningAppProcesses();
            if (appProcesses == null) {
                return false;
            }
            final String packageName = context.getPackageName();
            for (RunningAppProcessInfo appProcess : appProcesses) {
                if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                        && appProcess.processName.equals(packageName)) {
                    return true;
                }
            }
            return false;
        }
    }

The Manifest.xml in library project:

 <uses-permission android:name="com.myapp.libraryproject.permission.C2D_MESSAGE" />


 <receiver
            android:name="com.google.android.gcm.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="com.myapp.libraryproject" />
            </intent-filter>
        </receiver>

        <service android:name="com.myapp.libraryproject.GCMIntentService" /> 

The Manifest.xml in export Lite project (use library project as library):

 <uses-permission android:name="com.myapp.liteversion.permission.C2D_MESSAGE" />
 <receiver
                android:name="com.google.android.gcm.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="com.myapp.liteversion" />
                </intent-filter>
            </receiver>

            <service android:name="com.myapp.libraryproject.GCMIntentService" /> 

回答1:

Your problem is that com.google.android.gcm.GCMBroadcastReceiver assumes, by default, that the location of GCMIntentService is in the main package of your app, which in your case is com.myapp.liteversion. That's why it doesn't find the GCMIntentService class, which is actually in com.myapp.libraryproject.GCMIntentService.

The solution is to create a sub-class of GCMBroadcastReceiver (and use it in the manifest instead of the base class) and in it to override the following method :

protected String getGCMIntentServiceClassName(Context context) {
    return getDefaultIntentServiceClassName(context);
}

to something like :

protected String getGCMIntentServiceClassName(Context context) {
    return GCMIntentService.class.getName();
}