我正在尝试使用以下代码发送推送通知:
Message message = new Message.Builder().addData("appName", appData.name)
.addData("message", pushData.message).build();
在接收方,我的代码是:
String message = intent.getStringExtra("message");
当消息是英文,latin charset,一切正常。但是,当我尝试其他语言或字符ç时,它们会作为问号到达或从字符串中删除。
注意:它以utf-8编码
答案 0 :(得分:9)
Java服务器
Message messagePush = new Message.Builder().addData("message", URLEncoder.encode("your message éèçà", "UTF-8")))
Android应用
String message = URLDecoder.decode(intent.getStringExtra("message"), "UTF-8");
答案 1 :(得分:2)
我遇到了同样的问题。在Android客户端上收到损坏的非ASCII字符。我个人认为这是Google GCM服务器库实施中的一个问题。
在Android GCM库中,我看到了方法:
com.google.android.gcm.server.Sender.sendNoRetry(Message, List<String>)
该方法执行以下操作
HttpURLConnection conn = post(GCM_SEND_ENDPOINT, "application/json", requestBody)
他们应至少指定“application / json; charset = utf-8 ”或他们使用的任何编码,或者更好地强制它为UTF-8。 这不是一个大问题吗?
深入挖掘我找到了方法:
com.google.android.gcm.server.Sender.post(String, String, String)
确实:
byte[] bytes = body.getBytes()
为什么他们使用平台默认字符集?特别是因为它不太可能与设备默认字符集对齐。
解决方法
将以下属性作为参数传递给JVM“ -Dfile.encoding = UTF-8 ”这指示Java使用UTF-8作为平台默认字符集做什么比如“blah”.getBytes()。这是不好的做法,但是当它是别人的图书馆时你能做什么呢?
答案 2 :(得分:2)
我遇到了与gcm-server库类似的问题。我的解决方法是使用自定义发件人覆盖post
方法,并在getBytes()
调用中使用UTF8作为编码。
它适用于Google App Engine。
自定义发件人类的代码:
import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.util.logging.Level;
import com.google.android.gcm.server.Sender;
/**
* Workaround to avoid issue #13 of gcm-server
* @see https://code.google.com/p/gcm/issues/detail?id=13&q=encoding
*
* @author rbarriuso /at/ tribalyte.com
*
*/
public class Utf8Sender extends Sender {
private final String key;
public Utf8Sender(String key) {
super(key);
this.key = key;
}
@Override
protected HttpURLConnection post(String url, String contentType, String body) throws IOException {
if (url == null || body == null) {
throw new IllegalArgumentException("arguments cannot be null");
}
if (!url.startsWith("https://")) {
logger.warning("URL does not use https: " + url);
}
logger.fine("Utf8Sender Sending POST to " + url);
logger.finest("POST body: " + body);
byte[] bytes = body.getBytes(UTF8);
HttpURLConnection conn = getConnection(url);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", contentType);
conn.setRequestProperty("Authorization", "key=" + key);
OutputStream out = conn.getOutputStream();
try {
out.write(bytes);
} finally {
close(out);
}
return conn;
}
private static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
// ignore error
logger.log(Level.FINEST, "IOException closing stream", e);
}
}
}
}
答案 3 :(得分:2)
这些是一些很好的解决方案,但是他们没有帮助我,因为我使用主题消息来发送通知。根据{{3}}
HTTP标头必须包含以下标头: 授权:key = YOUR_API_KEY Content-Type:application / json for JSON; application / x-www-form-urlencoded; charset = UTF-8用于纯文本。 如果省略Content-Type,则假定格式为纯文本。
但是,因为我正在使用云端点和我的应用程序(已经在野外)期待json,以纯文本格式化请求是不可行的。解决方案是忽略上面的文档,在我的后端,格式化http请求标头:
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
像魔术一样,突然所有特殊字符(读取:日语)都会进入我的应用程序,而不会进行前端更改。我的完整http邮政编码低于( where payload = Cloud endpoint model object, converted to json<String> via Gson):
try {
URL url = new URL("https://gcm-http.googleapis.com/gcm/send");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
connection.setRequestProperty("Authorization", "key=" + API_KEY);
connection.setRequestMethod("POST");
byte[] bytes=payload.getBytes("UTF-8");
OutputStream out = connection.getOutputStream();
try {
out.write(bytes);
} finally {
out.close();
}
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
// OK
log.warning("OK");
} else {
// Server returned HTTP error code.
log.warning("some error "+connection.getResponseCode());
}
} catch (MalformedURLException e) {
// ...
}
答案 4 :(得分:0)
中断调试器并查看您认为发送的消息的字节