我退出应用程序时未收到GCM消息

时间:2013-05-06 13:07:21

标签: android google-cloud-messaging

这是我的客户端代码。当我在应用程序内部时,消息和通知工作正常,但当我没有应用程序时,应用程序内的消息不会显示,但通知工作。怎么了?提前谢谢

package com.example.androidgcmclient;

import android.os.Bundle;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gcm.GCMRegistrar;
import android.app.Activity;
import android.view.Menu;

public class MainActivity  extends Activity {

    // Replace the xxx with the project id generated from the Google console when
    // you defined a Google APIs project.
    private static final String SENDER_ID = "my_sender_id";

    // This tag is used in Log.x() calls
    private static final String TAG = "MainActivity";

    // This string will hold the lengthy registration id that comes
    // from GCMRegistrar.register()
    private String regId = "";

    // These strings are hopefully self-explanatory
    private String registrationStatus = "Not yet registered";
    private String broadcastMessage = "No broadcast message";

    // This intent filter will be set to filter on the string "GCM_RECEIVED_ACTION"
    IntentFilter gcmFilter;

    // textviews used to show the status of our app's registration, and the latest
    // broadcast message.
    TextView tvRegStatusResult;
    TextView tvBroadcastMessage;

    // This broadcastreceiver instance will receive messages broadcast
    // with the action "GCM_RECEIVED_ACTION" via the gcmFilter

    // A BroadcastReceiver must override the onReceive() event.
    private BroadcastReceiver gcmReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {


            broadcastMessage = intent.getExtras().getString("gcm");

            if (broadcastMessage != null) {
                // display our received message
                tvBroadcastMessage.setText(broadcastMessage);
                Log.d(TAG, "message received");


            }
        }
    };

    // Reminder that the onCreate() method is not just called when an app is first opened,
    // but, among other occasions, is called when the device changes orientation.
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvBroadcastMessage = (TextView) findViewById(R.id.tv_message);
        tvRegStatusResult = (TextView) findViewById(R.id.tv_reg_status_result);
        // Create our IntentFilter, which will be used in conjunction with a
        // broadcast receiver.
        gcmFilter = new IntentFilter();
        gcmFilter.addAction("GCM_RECEIVED_ACTION");

        registerClient();


    }

    // This registerClient() method checks the current device, checks the
    // manifest for the appropriate rights, and then retrieves a registration id
    // from the GCM cloud.  If there is no registration id, GCMRegistrar will
    // register this device for the specified project, which will return a
    // registration id.
    public void registerClient() {

        try {
            // Check that the device supports GCM (should be in a try / catch)
            GCMRegistrar.checkDevice(this);

            // Check the manifest to be sure this app has all the required
            // permissions.
            GCMRegistrar.checkManifest(this);

            // Get the existing registration id, if it exists.
            regId = GCMRegistrar.getRegistrationId(this);

            if (regId.equals("")) {

                registrationStatus = "Registering...";

                tvRegStatusResult.setText(registrationStatus);

                // register this device for this project
                GCMRegistrar.register(this, SENDER_ID);
                regId = GCMRegistrar.getRegistrationId(this);

                registrationStatus = "Registration Acquired";

                // This is actually a dummy function.  At this point, one
                // would send the registration id, and other identifying
                // information to your server, which should save the id
                // for use when broadcasting messages.
                sendRegistrationToServer();

            } else {

                registrationStatus = "Already registered "+GCMRegistrar.getRegistrationId(this);

          /*      GCMRegistrar.unregister(this); regId="";
                Toast.makeText(getApplicationContext(), "Unregistered", Toast.LENGTH_LONG).show();*/

            }


        } catch (Exception e) {

            e.printStackTrace();
            registrationStatus = e.getMessage();

        }

        Log.d(TAG, registrationStatus);
        tvRegStatusResult.setText(registrationStatus);
        Toast.makeText(getApplicationContext(), "reg acq "+regId, Toast.LENGTH_LONG).show();

        // This is part of our CHEAT.  For this demo, you'll need to
        // capture this registration id so it can be used in our demo web
        // service.
        Log.d(TAG, regId);

    }

    private void sendRegistrationToServer() {
        // This is an empty placeholder for an asynchronous task to post the
        // registration
        // id and any other identifying information to your server.
    }

    // If the user changes the orientation of his phone, the current activity
    // is destroyed, and then re-created.  This means that our broadcast message
    // will get wiped out during re-orientation.
    // So, we save the broadcastmessage during an onSaveInstanceState()
    // event, which is called prior to the destruction of the activity.
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {

        super.onSaveInstanceState(savedInstanceState);

        savedInstanceState.putString("BroadcastMessage", broadcastMessage);

    }

    // When an activity is re-created, the os generates an onRestoreInstanceState()
    // event, passing it a bundle that contains any values that you may have put
    // in during onSaveInstanceState()
    // We can use this mechanism to re-display our last broadcast message.

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {

        super.onRestoreInstanceState(savedInstanceState);

        broadcastMessage = savedInstanceState.getString("BroadcastMessage");
        tvBroadcastMessage.setText(broadcastMessage);

    }

    // If our activity is paused, it is important to UN-register any
    // broadcast receivers.
    @Override
    protected void onPause() {

        unregisterReceiver(gcmReceiver);
        super.onPause();
    }

    // When an activity is resumed, be sure to register any
    // broadcast receivers with the appropriate intent
    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(gcmReceiver, gcmFilter);

    }

    // There are no menus for this demo app.  This is just
    // boilerplate code.
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    // NOTE the call to GCMRegistrar.onDestroy()
    @Override
    public void onDestroy() {

        GCMRegistrar.onDestroy(this);

        super.onDestroy();
    }

}

和GCMIntentService类

package com.example.androidgcmclient;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import android.support.v4.app.NotificationCompat.Builder;
import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService  extends GCMBaseIntentService {

    private static final String SENDER_ID = "my_sender_id";

    private static final String TAG = "GCMIntentService";

    public GCMIntentService()
    {
        super(SENDER_ID);
        Log.d(TAG, "GCMIntentService init");
    }


    @Override
    protected void onError(Context ctx, String sError) {
        // TODO Auto-generated method stub
        Log.d(TAG, "Error: " + sError);

        Log.d(getClass().getSimpleName(), "onError: " + sError);

    }

    @Override
    protected void onMessage(Context context, Intent intent) {

        Log.d(TAG, "Message Received");

        String message = intent.getStringExtra("message");

        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        android.app.Notification notification = new android.app.Notification(
                R.drawable.ic_launcher, message,
                System.currentTimeMillis());

        Intent notificationIntent = new Intent(context, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

        notification.setLatestEventInfo(context,
                "Webexpenses Claim Report", message, pendingIntent);
        notificationManager.notify(10001, notification);


        sendGCMIntent(context, message);

        Log.d(getClass().getSimpleName(), "Message Received");


    }


    private void sendGCMIntent(Context ctx, String message) {

        Intent broadcastIntent = new Intent();
        broadcastIntent.setAction("GCM_RECEIVED_ACTION");

        broadcastIntent.putExtra("gcm", message);

        ctx.sendBroadcast(broadcastIntent);

    }


    @Override
    protected void onRegistered(Context ctx, String regId) {
        // TODO Auto-generated method stub
        // send regId to your server
        Log.d(TAG, regId);

        Log.d(getClass().getSimpleName(), "onRegistered: " + regId);
        Toast.makeText(this, regId, Toast.LENGTH_LONG).show();

    }

    @Override
    protected void onUnregistered(Context ctx, String regId) {
        // TODO Auto-generated method stub
        // send notification to your server to remove that regId

        Log.d(getClass().getSimpleName(), "onUnregistered: " + regId);

    }

    @Override
    protected boolean onRecoverableError(Context ctxt, String errorMsg) {
      Log.d(getClass().getSimpleName(), "onRecoverableError: " + errorMsg);

      return(true);
    }

}

Android清单文件

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <permission
        android:name="com.example.androidgcmclient.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.example.androidgcmclient.permission.C2D_MESSAGE" />

    <!-- receives GCM messages -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <!-- GCM connects to Google services -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- GCM requires a Google account -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

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

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

    <!-- wake the processor if a GCM message is received -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.androidgcmclient.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

         <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.example.androidgcmclient" />  
            </intent-filter>   
        </receiver>
        <service
            android:name=".GCMIntentService">
        </service>


    </application>

</manifest>

2 个答案:

答案 0 :(得分:1)

您不应该在Activity中包含gcm代码。声明GCMIntentService,即使您的应用未运行,也会触发此操作。从那里你可以启动你想要的任何活动。

android gcm

答案 1 :(得分:0)

如果您希望在应用程序未运行时可以访问接收器,则需要在清单中定义接收器。

<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="my_app_package" />
    </intent-filter>
</receiver>

您需要严格按照here的说明进行操作。