簡體   English   中英

使用Google Play服務時出現ConcurrentModificationException

[英]ConcurrentModificationException on with using google play services

我是android編程的新手。 我正在嘗試開發簡單的gcm測試應用程序以在gcm服務器上注冊該應用程序。 該代碼是

public class MainActivity extends ActionBarActivity implements OnClickListener {

Button btnRegId;
Context context;
EditText etRegId;
GoogleCloudMessaging gcm;
AtomicInteger msgId = new AtomicInteger();
String regid;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";


String SENDER_ID = "507707796382";
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
static final String TAG = "GCM";


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

    btnRegId = (Button) findViewById(R.id.btnGetRegId);
    etRegId = (EditText) findViewById(R.id.etRegId);
    if (checkPlayServices()) {
        btnRegId.setOnClickListener(this);
        gcm = GoogleCloudMessaging.getInstance(this);
        regid = getRegistrationId(context);

        if (regid.isEmpty()) {
            registerInBackground();
        }
    } else {
        Log.i(TAG, "No valid Google Play Services APK found.");
        Toast.makeText(getApplicationContext(), "No valid Google Play Services APK found.", Toast.LENGTH_LONG).show();
    }
}




/**
 * Gets the current registration ID for application on GCM service.
 *
 * 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 registration ID 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;
}

/**
 * @return Application's {@code SharedPreferences}.
 */
private SharedPreferences getGCMPreferences(Context context) {
    // This sample app persists the registration ID in shared preferences, but
    // how you store the registration ID in your app is up to you.
    return getSharedPreferences(MainActivity.class.getSimpleName(),
            Context.MODE_PRIVATE);
}

/**
 * @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 (PackageManager.NameNotFoundException e) {
        // should never happen
        throw new RuntimeException("Could not get package name: " + e);
    }
}

@Override
public void onClick(View view) {

}

@Override
protected void onResume() {
    super.onResume();
    checkPlayServices();
}

private boolean checkPlayServices() {
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
            GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                    PLAY_SERVICES_RESOLUTION_REQUEST).show();
        } else {
            Log.i("GCM", "This device is not supported.");
            finish();
        }
        return false;
    }

    return true;
}

/**
 * Registers the application with GCM servers asynchronously.
 *
 * Stores the registration ID and app versionCode in the application's
 * shared preferences.
 */
private void registerInBackground() {
    new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            String msg = "";
            try {
                if (gcm == null) {
                    gcm = GoogleCloudMessaging.getInstance(context);
                }
                regid = gcm.register(SENDER_ID);
                msg = "Device registered, registration ID=" + regid;

                // send the registration ID to server over HTTP,
                // so it can use GCM/HTTP or CCS to send messages to app.
                // The request to server should be authenticated if  app
                // is using accounts.
                sendRegistrationIdToBackend();

                // For this demo: we don't need to send it because the device
                // will send upstream messages to a server that echo back the
                // message using the 'from' address in the message.

                // Persist the registration ID - no need to register again.
                storeRegistrationId(context, regid);
            } catch (IOException ex) {
                msg = "Error :" + ex.getMessage();
                // 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.
            }
            return msg;
        }
        @Override
        protected void onPostExecute(String msg) {
            etRegId.setText(msg + "\n");

        }

            }.execute(null, null, null);
}

/**
 * Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
 * or CCS to send messages to your app. Not needed for this demo since the
 * device sends upstream messages to a server that echoes back the message
 * using the 'from' address in the message.
 */
private void sendRegistrationIdToBackend() {
    //  implementation .
}

/**
 * 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();
}

}

執行此操作時出現錯誤。 我的logcat窗口顯示:

03-15 09:48:58.052    2686-2702/com.example.bhaskar.mygcm E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.example.bhaskar.mygcm, PID: 2686
java.lang.RuntimeException: An error occured while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:300)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
        at java.util.concurrent.FutureTask.run(FutureTask.java:242)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)
 Caused by: java.lang.SecurityException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.REGISTER pkg=com.google.android.gms (has extras) } without permission com.google.android.c2dm.permission.RECEIVE
        at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1710)
        at android.app.ContextImpl.startService(ContextImpl.java:1687)
        at android.content.ContextWrapper.startService(ContextWrapper.java:515)
        at com.google.android.gms.gcm.GoogleCloudMessaging.e(Unknown Source)
        at com.google.android.gms.gcm.GoogleCloudMessaging.register(Unknown Source)
        at com.example.bhaskar.mygcm.MainActivity$1.doInBackground(MainActivity.java:158)
        at com.example.bhaskar.mygcm.MainActivity$1.doInBackground(MainActivity.java:150)
        at android.os.AsyncTask$2.call(AsyncTask.java:288)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)    
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)   
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)

在158號我有;

regid = gcm.register(SENDER_ID);

AndroidManifest.xml:

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

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="com.google.android.c2dm.permission.C2D_RECEIVE"/>

<permission android:name="com.google.android.c2dm.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="com.google.android.c2dm.permission.C2D_MESSAGE"/>

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <receiver android:name=".GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.C2D_SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
            <category android:name="com.example.bhaskar.mygcm"/>
        </intent-filter>

            </receiver>
    <service android:name=".GcmMessageHandler"/>



    <activity
        android:name=".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>
    <meta-data android:name="com.google.android.gms.version"
               android:value="@integer/google_play_services_version"/>
</application>
</manifest>

任何人都可以幫助我找出錯誤的地方,任何幫助將不勝感激。

您是否添加了

<uses-permission android:name=" com.google.android.c2dm.permission.RECEIVE " /> 
 <uses-permission android:name="com.google.android.c2dm.permission.C2D_MESSAGE">

在你的清單上? 日志貓說不。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM