GCM设备始终未注册

时间:2015-08-18 18:11:58

标签: android push-notification google-cloud-messaging

经过大量搜索并遵循本指南https://github.com/codepath/android_guides/wiki/Google-Cloud-Messaging

我的帖子请求的响应总是返回下面的错误,尽管我的设备已经注册。此外,我不知道这是否有帮助,但我正在使用android studio来部署我的应用程序。

{"multicast_id":xxxxx,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"NotRegistered"}]}

这是我在第一个活动中的代码

private GCMClientManager mPushClientManager;
    private final String PROJECT_NUMBER = "kkkkkk";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mPushClientManager = new GCMClientManager(this, PROJECT_NUMBER);
    mPushClientManager.registerIfNeeded(new GCMClientManager.RegistrationCompletedHandler() {
        @Override
        public void onSuccess(String registrationId, boolean isNewRegistration) {
            Toast.makeText(ChoicesActivity.this, registrationId,
                    Toast.LENGTH_SHORT).show();
            Log.e("test", "regId " + registrationId);
            // SEND async device registration to your back-end server
            // linking user with device registration id
            // POST https://my-back-end.com/devices/register?user_id=123&device_id=abc
        }

        @Override
        public void onFailure(String ex) {
            super.onFailure(ex);
            // If there is an error registering, don't just keep trying to register.
            // Require the user to click a button again, or perform
            // exponential back-off when retrying.
        }
    });
}

这是我的GCMClientManager

public class GCMClientManager {
    // Constants
    public static final String TAG = "GCMClientManager";
    public static final String EXTRA_MESSAGE = "message";
    public static final String PROPERTY_REG_ID = "registration_id";
    private static final String PROPERTY_APP_VERSION = "appVersion";
    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
    // Member variables
    private GoogleCloudMessaging gcm;
    private String regid;
    private String projectNumber;
    private Activity activity;

    public static abstract class RegistrationCompletedHandler {
        public abstract void onSuccess(String registrationId, boolean isNewRegistration);
        public void onFailure(String ex) {
            // If there is an error, don't just keep trying to register.
            // Require the user to click a button again, or perform
            // exponential back-off.
            Log.e(TAG, ex);
        }
    }

    public GCMClientManager(Activity activity, String projectNumber) {
        this.activity = activity;
        this.projectNumber = projectNumber;
        this.gcm = GoogleCloudMessaging.getInstance(activity);
    }

    // Register if needed or fetch from local store
    public void registerIfNeeded(final RegistrationCompletedHandler handler) {
        if (checkPlayServices()) {
            regid = getRegistrationId(getContext());

            if (regid.isEmpty()) {
                registerInBackground(handler);
            } else { // got id from cache
                Log.i(TAG, regid);
                handler.onSuccess(regid, false);
            }
        } else { // no play services
            Log.i(TAG, "No valid Google Play Services APK found.");
        }
    }

    /**
     * Registers the application with GCM servers asynchronously.
     * <p>
     * Stores the registration ID and app versionCode in the application's
     * shared preferences.
     */
    private void registerInBackground(final RegistrationCompletedHandler handler) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... params) {
                try {
                    if (gcm == null) {
                        gcm = GoogleCloudMessaging.getInstance(getContext());
                    }
                    InstanceID instanceID = InstanceID.getInstance(getContext());
                    regid = instanceID.getToken(projectNumber, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
                    Log.i(TAG, regid);

                    // Persist the regID - no need to register again.
                    storeRegistrationId(getContext(), regid);

                } catch (IOException ex) {
                    // If there is an error, don't just keep trying to register.
                    // Require the user to click a button again, or perform
                    // exponential back-off.
                    handler.onFailure("Error :" + ex.getMessage());
                }
                return regid;
            }

            @Override
            protected void onPostExecute(String regId) {
                if (regId != null) {
                    handler.onSuccess(regId, true);
                }
            }
        }.execute(null, null, null);
    }

    /**
     * Gets the current registration ID for application on GCM service.
     * <p>
     * If result is empty, the app needs to register.
     *
     * @return registration ID, or empty string if there is no existing
     *         registration ID.
     */
    private String getRegistrationId(Context context) {
        final SharedPreferences prefs = getGCMPreferences(context);
        String registrationId = prefs.getString(PROPERTY_REG_ID, "");
        if (registrationId.isEmpty()) {
            Log.i(TAG, "Registration not found.");
            return "";
        }

        // Check if app was updated; if so, it must clear the registration ID
        // since the existing regID is not guaranteed to work with the new
        // app version.
        int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
        int currentVersion = getAppVersion(context);
        if (registeredVersion != currentVersion) {
            Log.i(TAG, "App version changed.");
            return "";
        }
        return registrationId;
    }

    /**
     * Stores the registration ID and app versionCode in the application's
     * {@code SharedPreferences}.
     *
     * @param context application's context.
     * @param regId registration ID
     */
    private void storeRegistrationId(Context context, String regId) {
        final SharedPreferences prefs = getGCMPreferences(context);
        int appVersion = getAppVersion(context);
        Log.i(TAG, "Saving regId on app version " + appVersion);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString(PROPERTY_REG_ID, regId);
        editor.putInt(PROPERTY_APP_VERSION, appVersion);
        editor.commit();
    }

    /**
     * @return Application's version code from the {@code PackageManager}.
     */
    private static int getAppVersion(Context context) {
        try {
            PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (NameNotFoundException e) {
            // should never happen
            throw new RuntimeException("Could not get package name: " + e);
        }
    }

    private SharedPreferences getGCMPreferences(Context context) {
        // This sample app persists the registration ID in shared preferences, but
        // how you store the regID in your app is up to you.
        return getContext().getSharedPreferences(context.getPackageName(),
                Context.MODE_PRIVATE);
    }

    /**
     * Check the device to make sure it has the Google Play Services APK. If
     * it doesn't, display a dialog that allows users to download the APK from
     * the Google Play Store or enable it in the device's system settings.
     */
    private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getContext());
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(),
                        PLAY_SERVICES_RESOLUTION_REQUEST).show();
            } else {
                Log.i(TAG, "This device is not supported.");
            }
            return false;
        }
        return true;
    }

    private Context getContext() {
        return activity;
    }

    private Activity getActivity() {
        return activity;
    }
}

这是我的GCMMessageHandler

public class GCMMessageHandler extends GcmListenerService {
    public static final int MESSAGE_NOTIFICATION_ID = 435345;

    @Override
    public void onMessageReceived(String from, Bundle data) {
        String message = data.getString("message");

        createNotification(from, message);
    }

    // Creates notification based on title and body received
    private void createNotification(String title, String body) {
        Context context = getBaseContext();
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
                .setSmallIcon(R.mipmap.ic_launcher).setContentTitle(title)
                .setContentText(body);
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(MESSAGE_NOTIFICATION_ID, mBuilder.build());
    }

}

我的AndroidManifest.xml里面还有以下内容

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.demo" >

    <uses-permission android:name="android.permission.INTERNET" />
    <!-- To auto-complete the email text field in the login form with the user's emails -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- gcm -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <permission android:name="com.example.demo.gcm.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.example.demo.gcm.permission.C2D_MESSAGE" />

    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <category android:name="com.example.demo.gcmquickstart" />
        </intent-filter>
    </receiver>


    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="test"
        android:theme="@style/Theme.DesignDemo" >

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

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

        <service
            android:name=".notifications.GCMMessageHandler"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </service>


    </application>

</manifest>

这是我正在制作帖子请求的脚本

REGISTRATION_ID=xxxxxx

SERVER_KEY=xxxxx

curl --header "Authorization: key=$SERVER_KEY" --header  Content-Type:"application/json"  https://android.googleapis.com/gcm/send  -d  "{ \"data\" : {\"foo\": \"bar\"}, \"registration_ids\":[\"$REGISTRATION_ID\"]  }"

1 个答案:

答案 0 :(得分:0)

GCM回复&#39;未注册&#39;表示&#34;如果是NotRegistered,则应从服务器数据库中删除注册ID,因为该应用程序是从设备上卸载的,或者没有配置为接收com.google.android.c2dm.intent的广播接收器。收到意图。&#34;来自文档。检查从设备中卸载应用程序或在AndroidManifest中描述错误的broadcastreceiver时出现此错误的情况。您可以使用我的test gcm服务器测试GCM功能。希望,这对你有帮助。