android java.io.IOException:GCM客户端中的服务不可用

3htmauhk  于 2023-01-15  发布在  Android
关注(0)|答案(8)|浏览(107)

我想实现一个gcm客户端到一个现有的android应用程序。所以,通过以下this教程,我写了以下代码:

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

安卓主节日:

<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>

昨天一切正常,我可以检索注册ID。但现在,总是有一个IOExceptionSERVICE_NOT_AVAILABLE
我在我的三星Galaxy S5和Genymotion模拟器(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)
t40tm48m

t40tm48m1#

检查您设备的时间。Google无法使用错误的时间注册您的设备

u5rb5r59

u5rb5r592#

当我遇到这个问题时,对我起作用的是打开Google Play应用程序。
似乎在设备重新启动后,在尝试任何GCM注册之前,必须至少启动一次。

hgqdbh6s

hgqdbh6s3#

这是一个奇怪的问题,我通过将GCM代码移到onCreate()方法的末尾来解决它。
我猜在我尝试注册CGM时应用程序上下文尚未完全创建。它需要有效的上下文。

ghhkc1vu

ghhkc1vu4#

SERVICE_NOT_AVAILABLE也可能意味着设备在执行任务时离线:
第一个月第一个月:第一个月第二个月:java.util.concurrent.ExecutionExceptionjava.io.IOExceptionSERVICE_NOT_AVAILABLE
com.google.android.gms.tasks.zzw.getResult(谷歌安卓通用汽车公司:播放服务任务@@17.2.1:3)
因此,这可以通过在设备离线时不请求FCM令牌来解决,例如:

@Override
public void onNetworkAvailable() {
    FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
        Log.d(LOG_TAG, "FCM token: " + task.getResult());
    });
}
0ve6wy6x

0ve6wy6x5#

昨天我自己解决了这个问题。我按照演示应用程序,将registerInBackground()方法中的AsyncTask改为普通的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();
}

现在,它起作用了,但我不知道为什么。谁能解释一下原因吗?谢谢你的帮助!

ha5z0ras

ha5z0ras6#

如果您在模拟器中运行应用,则必须安装Google Play服务。
我最近从Google原生模拟器切换到GenyMotion模拟器,遇到了这个错误。后来我意识到GenyMotion图像不附带Google Play服务。安装后,问题解决了。

svujldwt

svujldwt7#

还要确保你的手机上有互联网!

guykilcj

guykilcj8#

    • 本机Firebase错误:[消息传递/未知] java. io. IO异常:java.util.concurrent.ExecutionException:java.io.IOException:服务不可用**

我知道这听起来很奇怪,但当测试设备上存在互联网连接问题时,会出现此错误。

相关问题