无法在工作线程上同步获取 firebase id 令牌
Unable to get firebase id token synchronously on worker thread
我有一个 class 扩展 FirebaseMessagingService,在 onMessageRecieve() 方法中我使用工作管理器安排工作。在工作 class 中,我想 POST Firebase Id 令牌到我的服务器(我正在使用同步截击请求)但是对于 Firebase IdToken 我在我的内部使用 Tasks.await()工作 class 但 logcat 显示以下错误:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.calendarapp, PID: 29746
java.lang.IllegalStateException: Must not be called on the main application thread
at com.google.android.gms.common.internal.Preconditions.checkNotMainThread(com.google.android.gms:play-services-basement@@17.1.1:51)
at com.google.android.gms.common.internal.Preconditions.checkNotMainThread(com.google.android.gms:play-services-basement@@17.1.1:48)
at com.google.android.gms.tasks.Tasks.await(Unknown Source:16)
at com.example.calendarapp.MyWorker.onComplete(MyWorker.java:130)
at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
FirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
FirebaseAuth mAuth;
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage);
scheduleJob();
}
private void scheduleJob() {
// [START dispatch_job]
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(MyWorker.class)
.setConstraints(constraints)
.build();
WorkManager.getInstance().beginWith(work).enqueue();
// [END dispatch_job]
}
public void sendNotification(){
....
}
}
我的工人class
public class MyWorker extends Worker {
Context context_i;
private static String url="https://my_url";
public MyWorker(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
context_i=context;
}
@Override
public Result doWork() {
final DatabaseHandler databaseHandler=new DatabaseHandler(context_i);
HashMap<String,String> map_post=getPostObject();
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, new JSONObject(map_post), future, future);
VolleySingleton.getmInstance(getApplicationContext()).addToRequestQueue(request);
try {
try {
databaseHandler.deleteDatabase();
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject response = future.get(60, TimeUnit.SECONDS);
Iterator<String> keys = response.keys();
while(keys.hasNext()){
String eventId= keys.next();
try {
JSONObject jsonObject = response.getJSONObject(eventId);
String marker="none";
if(jsonObject.has("markedAs")){
marker=jsonObject.getString("markedAs");
}
ArrayList<String> attachmentsList= new ArrayList<>();
ArrayList<String> attachmentNameList=new ArrayList<>();
if(jsonObject.has("attachments")) {
JSONObject attachmentJson = jsonObject.getJSONObject("attachments");
Iterator iterator = attachmentJson.keys();
while(iterator.hasNext()){
String name_of_attachment= (String) iterator.next();
attachmentsList.add(attachmentJson.getString(name_of_attachment));
attachmentNameList.add(name_of_attachment);
}
}
ListItems item =new ListItems(
jsonObject.getString("name"),
jsonObject.getString("desc"),
jsonObject.getString("byName"),
jsonObject.getString("date"),
"Time: "+jsonObject.getString("time"),
"Venue: "+jsonObject.getString("venue"),marker,eventId,attachmentsList
);
item.setNameList(attachmentNameList);
item.setPhotoUrl(jsonObject.getString("photoURL"));
databaseHandler.addEvent(item);
} catch (JSONException e) {
e.printStackTrace();
}
}
databaseHandler.close();
Log.d("worker_tag", response.toString());
return Result.success();
} catch (InterruptedException e) {
e.printStackTrace();
// exception handling
return Result.failure();
} catch (ExecutionException e) {
e.printStackTrace();
return Result.failure();
// exception handling
} catch (TimeoutException e) {
e.printStackTrace();
return Result.failure();
}
}
public HashMap<String,String> getPostObject() {
final HashMap<String,String> mapToken=new HashMap<String, String>();
FirebaseAuth mAuth = FirebaseAuth.getInstance();
final FirebaseUser user = mAuth.getCurrentUser();
if (user != null) {
user.getIdToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onComplete(@NonNull Task<GetTokenResult> task) {
try {
Tasks.await(task);
if(task.isSuccessful()){
mapToken.put("token", Objects.requireNonNull(task.getResult()).getToken());
Log.d("PostToken", Objects.requireNonNull(task.getResult().getToken()));
Log.d("PostObject", String.valueOf(new JSONObject(mapToken)));
}
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
return mapToken;
}
Work class 不是后台线程吗?如果是那么为什么错误显示“不得应用于主应用程序线程”?
提前致谢。
user.getIdToken(true)
returns一个Task<GetTokenResult>
。由于您已经在后台线程中,因此根本不应使用 addOnCompleteListener()
- 只需立即调用 Tasks.await()
即可同步获取结果。
if (user != null) {
Task<GetTokenResult> task = user.getIdToken(true)
try {
GetTokenResult result = Tasks.await(task);
mapToken.put("token", Objects.requireNonNull(result).getToken());
Log.d("PostToken", Objects.requireNonNull(result).getToken()));
Log.d("PostObject", String.valueOf(new JSONObject(mapToken)));
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
我有一个 class 扩展 FirebaseMessagingService,在 onMessageRecieve() 方法中我使用工作管理器安排工作。在工作 class 中,我想 POST Firebase Id 令牌到我的服务器(我正在使用同步截击请求)但是对于 Firebase IdToken 我在我的内部使用 Tasks.await()工作 class 但 logcat 显示以下错误:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.calendarapp, PID: 29746
java.lang.IllegalStateException: Must not be called on the main application thread
at com.google.android.gms.common.internal.Preconditions.checkNotMainThread(com.google.android.gms:play-services-basement@@17.1.1:51)
at com.google.android.gms.common.internal.Preconditions.checkNotMainThread(com.google.android.gms:play-services-basement@@17.1.1:48)
at com.google.android.gms.tasks.Tasks.await(Unknown Source:16)
at com.example.calendarapp.MyWorker.onComplete(MyWorker.java:130)
at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
FirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
FirebaseAuth mAuth;
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage);
scheduleJob();
}
private void scheduleJob() {
// [START dispatch_job]
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(MyWorker.class)
.setConstraints(constraints)
.build();
WorkManager.getInstance().beginWith(work).enqueue();
// [END dispatch_job]
}
public void sendNotification(){
....
}
}
我的工人class
public class MyWorker extends Worker {
Context context_i;
private static String url="https://my_url";
public MyWorker(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
context_i=context;
}
@Override
public Result doWork() {
final DatabaseHandler databaseHandler=new DatabaseHandler(context_i);
HashMap<String,String> map_post=getPostObject();
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, new JSONObject(map_post), future, future);
VolleySingleton.getmInstance(getApplicationContext()).addToRequestQueue(request);
try {
try {
databaseHandler.deleteDatabase();
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject response = future.get(60, TimeUnit.SECONDS);
Iterator<String> keys = response.keys();
while(keys.hasNext()){
String eventId= keys.next();
try {
JSONObject jsonObject = response.getJSONObject(eventId);
String marker="none";
if(jsonObject.has("markedAs")){
marker=jsonObject.getString("markedAs");
}
ArrayList<String> attachmentsList= new ArrayList<>();
ArrayList<String> attachmentNameList=new ArrayList<>();
if(jsonObject.has("attachments")) {
JSONObject attachmentJson = jsonObject.getJSONObject("attachments");
Iterator iterator = attachmentJson.keys();
while(iterator.hasNext()){
String name_of_attachment= (String) iterator.next();
attachmentsList.add(attachmentJson.getString(name_of_attachment));
attachmentNameList.add(name_of_attachment);
}
}
ListItems item =new ListItems(
jsonObject.getString("name"),
jsonObject.getString("desc"),
jsonObject.getString("byName"),
jsonObject.getString("date"),
"Time: "+jsonObject.getString("time"),
"Venue: "+jsonObject.getString("venue"),marker,eventId,attachmentsList
);
item.setNameList(attachmentNameList);
item.setPhotoUrl(jsonObject.getString("photoURL"));
databaseHandler.addEvent(item);
} catch (JSONException e) {
e.printStackTrace();
}
}
databaseHandler.close();
Log.d("worker_tag", response.toString());
return Result.success();
} catch (InterruptedException e) {
e.printStackTrace();
// exception handling
return Result.failure();
} catch (ExecutionException e) {
e.printStackTrace();
return Result.failure();
// exception handling
} catch (TimeoutException e) {
e.printStackTrace();
return Result.failure();
}
}
public HashMap<String,String> getPostObject() {
final HashMap<String,String> mapToken=new HashMap<String, String>();
FirebaseAuth mAuth = FirebaseAuth.getInstance();
final FirebaseUser user = mAuth.getCurrentUser();
if (user != null) {
user.getIdToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onComplete(@NonNull Task<GetTokenResult> task) {
try {
Tasks.await(task);
if(task.isSuccessful()){
mapToken.put("token", Objects.requireNonNull(task.getResult()).getToken());
Log.d("PostToken", Objects.requireNonNull(task.getResult().getToken()));
Log.d("PostObject", String.valueOf(new JSONObject(mapToken)));
}
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
return mapToken;
}
Work class 不是后台线程吗?如果是那么为什么错误显示“不得应用于主应用程序线程”?
提前致谢。
user.getIdToken(true)
returns一个Task<GetTokenResult>
。由于您已经在后台线程中,因此根本不应使用 addOnCompleteListener()
- 只需立即调用 Tasks.await()
即可同步获取结果。
if (user != null) {
Task<GetTokenResult> task = user.getIdToken(true)
try {
GetTokenResult result = Tasks.await(task);
mapToken.put("token", Objects.requireNonNull(result).getToken());
Log.d("PostToken", Objects.requireNonNull(result).getToken()));
Log.d("PostObject", String.valueOf(new JSONObject(mapToken)));
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}