Java.io.IOException: SERVICE_NOT_AVAILABLE в GCM Client

Я хочу внедрить gcm-клиент в существующее приложение для Android. Итак, следуя этому руководству, я написал следующий код:

public class RegisterForGCMAsyncTask extends AbstractSecureOperationTask { ... @Override protected Boolean doInBackground(String... params) { String token = authenticate(); getRegId(); if (TextUtils.isEmpty(registrationId)) { return false; } // try { URL url = convertToURLEscapingIllegalCharacters(String.format(Constants.REGISTER_URL, registrationId, userId, token)); URLConnection connection = url.openConnection(); InputStreamReader streamReader = new InputStreamReader(connection.getInputStream()); JSONParser parser = new JSONParser(); JSONObject rootObj = (JSONObject) parser.parse(streamReader); String status = rootObj.get("status").toString(); if (status.equals("OK")) { return true; } } catch (ParseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return false; } private void getRegId() { try { if (gcm == null) { gcm = GoogleCloudMessaging.getInstance(context); } registrationId = gcm.register(PROJECT_ID); } catch (IOException e) { Log.e(LOG_TAG, e.getMessage(), e); } } } 

AndroidMainfest:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.xxxxxxxx.xxxxxxxx" android:versionCode="20140617" android:versionName="2.0.0"> <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19"/> <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="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> <permission android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE" android:protectionLevel="signature"/> <uses-permission android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE"/> <permission android:name="de.xxxxxxxx.xxxxxxxx.permission.C2D_MESSAGE" android:protectionLevel="signature"/> <uses-permission android:name="de.xxxxxxxx.xxxxxxxx.permission.C2D_MESSAGE"/> <!-- Maps API needs OpenGL ES 2.0. --> <uses-feature android:glEsVersion="0x00020000" android:required="true"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name="de.retterapps.Handyalarm.views.activities.MainActivity" android:configChanges="orientation|screenLayout|screenSize|layoutDirection" android:label="@string/app_name" android:theme="@style/AppTheme"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <receiver android:name=".helper.gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE"/> <category android:name="de.xxxxxxxx.xxxxxxxx"/> </intent-filter> </receiver> <service android:name=".helper.gcm.GcmMessageHandler"/> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/> <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="xxxxxxxx"/> </application> Размер <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.xxxxxxxx.xxxxxxxx" android:versionCode="20140617" android:versionName="2.0.0"> <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19"/> <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="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> <permission android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE" android:protectionLevel="signature"/> <uses-permission android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE"/> <permission android:name="de.xxxxxxxx.xxxxxxxx.permission.C2D_MESSAGE" android:protectionLevel="signature"/> <uses-permission android:name="de.xxxxxxxx.xxxxxxxx.permission.C2D_MESSAGE"/> <!-- Maps API needs OpenGL ES 2.0. --> <uses-feature android:glEsVersion="0x00020000" android:required="true"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name="de.retterapps.Handyalarm.views.activities.MainActivity" android:configChanges="orientation|screenLayout|screenSize|layoutDirection" android:label="@string/app_name" android:theme="@style/AppTheme"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <receiver android:name=".helper.gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE"/> <category android:name="de.xxxxxxxx.xxxxxxxx"/> </intent-filter> </receiver> <service android:name=".helper.gcm.GcmMessageHandler"/> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/> <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="xxxxxxxx"/> </application> 

Вчера все работало нормально, и я мог получить идентификатор регистрации. Но теперь всегда существует IOException SERVICE_NOT_AVAILABLE .

Я тестировал его на своем Samsung Galaxy S5 и в Genymotion Emulator (Android 4.1.2), но я получаю всегда одинаковые результаты. Кто-нибудь знает, как решить проблему?

редактировать

Вот полный стек:

 java.io.IOException: SERVICE_NOT_AVAILABLE at com.google.android.gms.gcm.GoogleCloudMessaging.register(Unknown Source) at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.getRegId(RegisterForGCMAsyncTask.java:72) at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.doInBackground(RegisterForGCMAsyncTask.java:43) at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.doInBackground(RegisterForGCMAsyncTask.java:24) at android.os.AsyncTask$2.call(AsyncTask.java:287) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask.run(FutureTask.java:137) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) at java.lang.Thread.run(Thread.java:856) 

Проверьте время вашего устройства. Google не может зарегистрировать ваше устройство с неправильным временем

Когда я столкнулся с этой проблемой, мне удавалось открыть приложение Google Play.

Кажется, что он должен запускаться по крайней мере один раз после перезапуска устройства перед любой попыткой регистрации GCM.

Это странно. Я решил это, переместив код GCM в конец моего метода onCreate ().

Я предполагаю, что приложение Контекст не был полностью создан к моменту, когда я попытался зарегистрироваться для CGM. Для этого нужен действительный контекст.

Вчера я решил проблему самостоятельно. Я выполнил демо-приложение и изменил AsyncTask в методе registerInBackground () – на простой поток Java. Вот код:

 private void registerInBackground() { final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0: Toast.makeText(context, getString(R.string.txt_gcm_registered), Toast.LENGTH_LONG).show(); break; case 1: Toast.makeText(context, getString(R.string.error_register_gcm), Toast.LENGTH_LONG).show(); break; } super.handleMessage(msg); } }; Runnable runnable = new Runnable() { @Override public void run() { try { if (gcm == null) { gcm = GoogleCloudMessaging.getInstance(context); } regId = gcm.register(Constants.SENDER_ID); if (sendRegistrationIdToBackend(regId)) { handler.sendEmptyMessage(0); } else { handler.sendEmptyMessage(1); } storeRegistrationId(context, regId); } catch (IOException ex) { handler.sendEmptyMessage(1); Log.e(LOG_TAG, ex.getMessage(), ex); } } }; new Thread(runnable).start(); } 

Теперь он работает, но я не знаю, почему. Может ли кто-нибудь объяснить причину? Спасибо за вашу помощь!

Если вы запускаете свое приложение в эмуляторе, вы должны установить Google Play Service.

Недавно я переключился на эмулятор GenyMotion из собственного эмулятора Google и столкнулся с этой ошибкой. Позже я понял, что образ GenyMotion не поставляется с Google Play Service. После установки проблема решена.