Java.io.IOException: SERVICE_NOT_AVAILABLE en el cliente de GCM

Quiero implementar un cliente gcm en una aplicación android existente. Por lo tanto, siguiendo este tutorial escribí código siguiente:

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> 

Ayer todo funcionó bien y pude recuperar el ID de registro. Pero ahora, siempre hay una IOException diciendo SERVICE_NOT_AVAILABLE .

Lo probé en mi Samsung Galaxy S5 y en el Emulador de Genymotion (Android 4.1.2), pero estoy recibiendo siempre los mismos resultados. ¿Alguien tiene una idea de cómo resolver el problema?

Editar

Aquí está el stacktrace completo:

 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) 

Compruebe la hora de su dispositivo. Google no puede registrar tu dispositivo con un tiempo incorrecto

Cuando encontré este problema, lo que funcionó para mí fue abrir la aplicación de Google Play.

Parece que debe iniciarse al menos una vez después de reiniciar el dispositivo antes de cualquier intento de registro de GCM.

Esto es extraño. Lo solucioné moviendo el código GCM al final de mi método onCreate ().

Mi conjetura es el contexto de la aplicación no fue creada totalmente por el tiempo que intenté registrar para CGM. Necesita un Contexto válido.

Ayer resolví el problema por mi cuenta. Seguí la aplicación de demostración y cambié el AsyncTask en el método registerInBackground () – a un simple hilo java. Aquí está el código:

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

Ahora, está funcionando, pero no sé por qué. ¿Alguien puede explicar la razón? ¡Gracias por tu ayuda!

Si está ejecutando su aplicación en el emulador, debe instalar Google Play Service.

Hace poco cambié a GenyMotion Emulator de emulador nativo de Google y encontré este error. Más tarde me di cuenta de que la imagen de GenyMotion no viene con Google Play Service. Después de la instalación, se resuelve el problema.

  • Android: Multithreading-Bluetooth SPP / RFCOMM-Cómo mantener activo mi BluetoothSocket y OutputStream al cambiar Actividades
  • Antecedentes Proceso para escanear la ubicación del usuario a intervalos regulares y actualizar la base de datos local incluso cuando la aplicación no está abierta
  • Android Service Exchange siempre se bloquea
  • El servicio de Android que se estaba ejecutando cuando se apagó el teléfono se inicia automáticamente cuando se inicia el teléfono
  • La vinculación al servicio que ya fue iniciada por BroadcastReceiver crea una nueva instancia de servicio
  • ¿Cómo comprobar si los servicios de ubicación están habilitados?
  • ¿Por qué no comienza este servicio simple?
  • ¿Cómo puedo eliminar una notificación de primer plano en Android Lollipop?
  • No se le permite enlazar con el servicio
  • Servicio de fondo en Android - Necesita ayuda
  • servicio androide para realizar un seguimiento de las llamadas salientes y SMS en segundo plano
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.