FCM onTokenRefresh()无法在未调用Looper.prepare()

时间:2017-03-16 08:12:03

标签: android firebase firebase-cloud-messaging

我有一个应用程序,无论何时调用API,我都会使用Firebase Cloud Messaging服务从我自己的服务器获取通知,奇怪的是当我通过Android studio RUN菜单安装它时,这是将应用程序直接安装到我的设备APP工作正常,但是当我从我的项目目录中进行app-debug并手动安装时,它会给我错误

Can't create handler inside thread that has not called Looper.prepare()

错误指出我的方法是使用onTokenRefresh()方法中的排球库将数据发送到我的数据库。

我将这些方法放在扩展FirebaseInstanceIdService的服务中。

这是完整的错误消息

E/AndroidRuntime: FATAL EXCEPTION: pool-3-thread-1
   Process: proizzy.com.qrcodeproizzyadm, PID: 5704
   java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
   at android.os.Handler.<init>(Handler.java:200)
   at android.os.Handler.<init>(Handler.java:114)
   at android.widget.Toast$TN.<init>(Toast.java:645)
   at android.widget.Toast.<init>(Toast.java:137)
   at android.widget.Toast.makeText(Toast.java:440)
   at proizzy.com.qrcodeproizzyadm.Notification.FirebaseInstanceIDService.onTokenRefresh(FirebaseInstanceIDService.java:25)
   at com.google.firebase.iid.FirebaseInstanceIdService.zza(Unknown Source)
   at com.google.firebase.iid.FirebaseInstanceIdService.zzm(Unknown Source)
   at com.google.firebase.iid.zzb$2.run(Unknown Source)
   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)

我对我的代码出了什么问题一无所知。

这是我完整的服务类代码

public class FirebaseInstanceIDService extends FirebaseInstanceIdService {

@Override
public void onTokenRefresh() {
    final String token = FirebaseInstanceId.getInstance().getToken();
    Log.v("tok", token);

    String tokUrl = "someurl.php";
    JsonObjectRequest regToken = new JsonObjectRequest(Request.Method.POST, tokUrl, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    Log.v("success", response.toString());
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.v("errorvolley", error.getMessage());
        }
    }){
        @Override
        protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<>();
            params.put("token", token);
            return params;
        }
    };

    RequestQueue regQueue = Volley.newRequestQueue(getApplicationContext());
    regQueue.add(regToken);

}

4 个答案:

答案 0 :(得分:1)

好的,所以我已经解决了这些问题,出于某种原因,如果你从debug-app手动安装app,你会得到我在问题中提到的错误。我通过将我从FCM获得的令牌保存到共享首选项来解决它,之后当用户登录时,我将令牌发送到我的数据库。这种方式imo效率较低,因为用户每次登录时都必须发送令牌,但令牌保持不变(直到他们清除数据和/或卸载应用程序)。

答案 1 :(得分:0)

您提供给我们的代码不是产生错误的代码版本。后者正在创造一个祝酒词。 onTokenRefresh()在后台线程上调用,无法直接显示Toast。

专注于在设备上获取正确版本的应用程序(没有Toast的应用程序),问题就会消失。

答案 2 :(得分:0)

您遇到的问题是,您已经在工作线程/后台线程中时尝试执行异步任务。 如您在堆栈跟踪中所见,您(系统)创建了一个只能从主线程调用的处理程序:         android.os.Handler。(Handler.java:114)
解决方案: 添加这样的支票:

if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
    // do stuff that is allowed on main thread
} else {  
    // do stuff that is allowed on background thread
}

答案 3 :(得分:0)

怎么样?

$ sed 's/\(S\.\)\(.\)/\1\n\2/g' file
1900-01-01 00:00:00|1|S|S|S|S.
1900-01-01|S.
1900-01-01 00:00:00|1|S|S|S|S.
1900-01-01 00:00:00|1|S|S|S|S.