我有一个非常困惑的问题。我正在设置一个管理应用,该应用将使用Firebase Cloud Messaging
向目标客户端发送推送通知。它工作了一段时间,然后突然停止工作,我没有对代码进行任何更改-这是令人困惑的部分!
这是Firebase配置。
FirebaseConfiguration.java
@Configuration
public class FirebaseConfig {
private final String databaseUrl;
private final String configPath;
@Inject
public FirebaseConfig(
@Value("${firebase.database.url}") String databaseUrl,
@Value("${firebase.config.path}") String configPath) {
this.databaseUrl = databaseUrl;
this.configPath = configPath;
}
@Bean
public DatabaseReference firebaseDatabase() {
return FirebaseDatabase.getInstance().getReference();
}
@PostConstruct
public void init() throws IOException {
/*
* https://firebase.google.com/docs/admin/setup Create service account; Download .json config file
*/
final InputStream serviceAccount = FirebaseConfig.class.getClassLoader().getResourceAsStream(configPath);
final FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl(databaseUrl)
.build();
FirebaseApp.initializeApp(options);
}
}
在这里,configPath
是.json
文件的路径,其中包含我的Firebase应用程序的所有配置,该配置是在应用程序的Firebase控制台中生成的。
myapp-firebase-config.json
{
"type": "service_account",
"project_id": "myapp",
"private_key_id": "8564e07po7cff976068c702dcdpodbbb0cu3e6",
"private_key": "-----BEGIN PRIVATE KEY-----...\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-jo9yp@myapp.iam.gserviceaccount.com",
"client_id": "12345",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-jo9yp%myapp.iam.gserviceaccount.com"
}
现在,尝试发送推送通知但失败的代码。
Message message = Message.builder()
.putData("Message", "Test 123")
.setToken(token)
.build();
ApiFuture<String> response = FirebaseMessaging.getInstance().sendAsync(message);
final String result = response.get(); // throws the exception
正在引发的异常的堆栈跟踪如下:
java.util.concurrent.ExecutionException: java.lang.NullPointerException
at com.google.firebase.tasks.Tasks.getResultOrThrowExecutionException(Tasks.java:179)
at com.google.firebase.tasks.Tasks.await(Tasks.java:102)
at com.google.firebase.internal.TaskToApiFuture.get(TaskToApiFuture.java:74)
at com.newfaces.businesslogic.logic.MessageRequestLogicBean$1.run(MessageRequestLogicBean.java:75)
at com.google.firebase.internal.TaskToApiFuture$1.onComplete(TaskToApiFuture.java:50)
at com.google.firebase.tasks.OnCompleteCompletionListener$1.run(OnCompleteCompletionListener.java:54)
at com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(MoreExecutors.java:399)
at com.google.firebase.tasks.OnCompleteCompletionListener.onComplete(OnCompleteCompletionListener.java:48)
at com.google.firebase.tasks.TaskCompletionListenerQueue.flush(TaskCompletionListenerQueue.java:81)
at com.google.firebase.tasks.TaskImpl.setException(TaskImpl.java:115)
at com.google.firebase.tasks.Tasks$1.run(Tasks.java:84)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:213)
at com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:127)
at com.google.api.client.json.jackson2.JacksonFactory.createJsonParser(JacksonFactory.java:98)
at com.google.firebase.messaging.FirebaseMessaging.handleSendHttpError(FirebaseMessaging.java:251)
at com.google.firebase.messaging.FirebaseMessaging.makeSendRequest(FirebaseMessaging.java:238)
我在FirebaseMessaging
类中发现了引发此异常的根代码段:
private void handleSendHttpError(HttpResponseException e) throws FirebaseMessagingException {
MessagingServiceErrorResponse response = new MessagingServiceErrorResponse();
try {
JsonParser parser = jsonFactory.createJsonParser(e.getContent()); // HERE e.getContent() == null which throws the NullPointerException
parser.parseAndClose(response);
} catch (IOException ignored) {
// ignored
}
String code = FCM_ERROR_CODES.get(response.getString("status"));
if (code == null) {
code = UNKNOWN_ERROR;
}
String msg = response.getString("message");
if (Strings.isNullOrEmpty(msg)) {
msg = String.format("Unexpected HTTP response with status: %d; body: %s",
e.getStatusCode(), e.getContent());
}
throw new FirebaseMessagingException(code, msg, e);
}
现在,鉴于此操作实际上未返回异常,因此无法进行调试,但我查看了Firebase API Metrics
,发现服务器正在返回错误代码401 - Unauthorized
。因此,为了验证这一点,我按照https://developers.google.com/cloud-messaging/http#checkAPIkey做了一个curl
:
# server_key=YOUR_SERVER_KEY
# curl --header "Authorization: key=$server_key" \
--header Content-Type:"application/json" \
https://gcm-http.googleapis.com/gcm/send \
-d "{\"registration_ids\":[\"ABC\"]}"
我得到的答复是:
{"multicast_id":6706957967213497648,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1532214216265421%fa1b6a1df9fd7ecd"}]}
...表示该请求已针对我在应用程序中使用的给定server_key和registration_token(registration_id)被授权。
那让我完全迷失了。由于相同的令牌会从应用程序中获得Unathorized,因此curl
被授权时,它是完全授权的。我不知道该如何进行,非常感谢您的帮助。
仅需提及的是,我还尝试了在有效的dryRun
模式下运行。