- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
嘿,我在调用 `subscribeToTopicP 类时遇到了一些 Gcm Intent 服务的问题,总是出现空指针异常。
这是我的代码:
GcmIntentService.java
private static final String TAG = GcmIntentService.class.getSimpleName();
public GcmIntentService() {
super(TAG);
}
public static final String KEY = "key";
public static final String TOPIC = "topic";
public static final String SUBSCRIBE = "subscribe";
public static final String UNSUBSCRIBE = "unsubscribe";
public SessionManager session;
@Override
protected void onHandleIntent(Intent intent) {
session = new SessionManager(getApplicationContext());
String key = intent.getStringExtra(KEY);
switch (key) {
case SUBSCRIBE:
// subscribe to a topic
String topic = intent.getStringExtra(TOPIC);
subscribeToTopic(topic);
break;
case UNSUBSCRIBE:
break;
default:
// if key is specified, register with GCM
registerGCM();
}
}
/**
* Registering with GCM and obtaining the gcm registration id
*/
private void registerGCM() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Log.e(TAG, "GCM Registration Token: " + token);
// sending the registration id to our server
sendRegistrationToServer(token);
sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, true).apply();
} catch (Exception e) {
Log.e(TAG, "Failed to complete token refresh", e);
sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
private void sendRegistrationToServer(final String token) {
// checking for valid login session
session.isLoggedIn();
HashMap<String, String> user = session.getUserDetails();
String UserId = user.get(SessionManager.KEY_ID);
String endPoint = EndPoints.UPDATE_USER_GCM.replace("_ID_", UserId);
Log.e(TAG, "endpoint: " + endPoint);
StringRequest strReq = new StringRequest(Request.Method.PUT, endPoint, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.e(TAG, "response: " + response);
try {
JSONObject obj = new JSONObject(response);
// check for error
if (obj.getBoolean("error") == false) {
// broadcasting token sent to server
Intent registrationComplete = new Intent(Config.SENT_TOKEN_TO_SERVER);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(registrationComplete);
} else {
Toast.makeText(getApplicationContext(), "Unable to send gcm registration id to our sever. " + obj.getJSONObject("error").getString("message"), Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
Log.e(TAG, "json parsing error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Json parse error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
Log.e(TAG, "Volley error: " + error.getMessage() + ", code: " + networkResponse);
Toast.makeText(getApplicationContext(), "Volley error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("UserGcmRegistrationId", token);
Log.e(TAG, "params: " + params.toString());
return params;
}
};
//Adding request to request queue
Volley.newRequestQueue(getApplicationContext()).add(strReq);
}
/**
* Subscribe to a topic
*/
public static void subscribeToTopic(String topic) {
GcmPubSub pubSub = GcmPubSub.getInstance(MyApplication.getInstance().getApplicationContext());
InstanceID instanceID = InstanceID.getInstance(MyApplication.getInstance().getApplicationContext());
String token = null;
try {
token = instanceID.getToken(MyApplication.getInstance().getApplicationContext().getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null) {
pubSub.subscribe(token, "/topics/" + topic, null);
Log.e(TAG, "Subscribed to topic: " + topic);
} else {
Log.e(TAG, "error: gcm registration id is null");
}
} catch (IOException e) {
Log.e(TAG, "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage());
Toast.makeText(MyApplication.getInstance().getApplicationContext(), "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void unsubscribeFromTopic(String topic) {
GcmPubSub pubSub = GcmPubSub.getInstance(getApplicationContext());
InstanceID instanceID = InstanceID.getInstance(getApplicationContext());
String token = null;
try {
token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null) {
pubSub.unsubscribe(token, "");
Log.e(TAG, "Unsubscribed from topic: " + topic);
} else {
Log.e(TAG, "error: gcm registration id is null");
}
} catch (IOException e) {
Log.e(TAG, "Topic unsubscribe error. Topic: " + topic + ", error: " + e.getMessage());
Toast.makeText(getApplicationContext(), "Topic subscribe error. Topic: " + topic + ", error: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
我的 LogCat 错误:
E/AndroidRuntime: FATAL EXCEPTION: IntentService[GcmIntentService]
Process: com.nvitek.www.aspirasirakyat, PID: 25962
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:107)
at com.nvitek.www.aspirasirakyat.gcm.GcmIntentService.subscribeToTopic(GcmIntentService.java:155)
at com.nvitek.www.aspirasirakyat.gcm.GcmIntentService.onHandleIntent(GcmIntentService.java:56)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
MyApplication.java
public static final String TAG = MyApplication.class.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
private SessionManager pref;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
if(mInstance==null)
{
mInstance=new MyApplication();
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public SessionManager getPrefManager() {
if (pref == null) {
pref = new SessionManager(this);
}
return pref;
}
这是我的 ActivityDashboard.java
//JSON TAGS
public static final String TAG_IMAGE_URL = "image";
public static final String TAG_TITLE = "title";
public static final String TAG_FNAME = "fname";
public static final String TAG_LNAME = "lname";
public static final String TAG_CONTENT = "content";
public static final String TAG_DATE = "date";
public static final String TAG_ID = "id";
private String TAG = ActivityDashboard.class.getSimpleName();
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private BroadcastReceiver mRegistrationBroadcastReceiver;
private List<ListItem> listItems;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
//Volley Request Queue
private RequestQueue requestQueue;
private Boolean exit = false;
SessionManager session;
JSONArray users = null;
DrawerLayout drawerLayout;
NavigationView mNavigationView;
private GoogleApiClient client;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
session = new SessionManager(getApplicationContext());
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_menu_white);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigationView = (NavigationView) findViewById(R.id.navigation);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
Intent intent;
switch (menuItem.getItemId()) {
case R.id.navigation_item_1:
intent = new Intent(ActivityDashboard.this, ActivityDashboard.class);
startActivity(intent);
return true;
/* case R.id.navigation_item_2:
intent = new Intent(ActivityDashboard.this, ActivityDashboard.class);
startActivity(intent);
return true; */
case R.id.navigation_item_3:
intent = new Intent(ActivityDashboard.this, ActivityStatistic.class);
startActivity(intent);
return true;
case R.id.navigation_item_4:
intent = new Intent(ActivityDashboard.this, ActivityProfile.class);
startActivity(intent);
return true;
case R.id.navigation_item_5:
session.logoutUser();
return true;
default:
return true;
}
}
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Loading...", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
gotoAdd(view);
}
});
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
subscribeToGlobalTopic();
} else if (intent.getAction().equals(Config.SENT_TOKEN_TO_SERVER)) {
// gcm registration id is stored in our server's MySQL
Log.e(TAG, "GCM registration id is sent to our server");
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
handlePushNotification(intent);
}
}
};
}
@Override
public void onStart() {
super.onStart();
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(ActivityDashboard.this, recyclerView, new ClickListener() {
@Override
public void onListClick(View v, int position) {
Intent intent = new Intent(ActivityDashboard.this, ActivityPreviewPost.class);
intent.putExtra("Url_Key", EndPoints.COMMENTS + "?id=" + listItems.get(position).getId());
intent.putExtra("Id_Key", listItems.get(position).getId());
intent.putExtra("Photo_Key", listItems.get(position).getImageUrl());
intent.putExtra("Title_Key", listItems.get(position).getTitle());
intent.putExtra("FName_Key", listItems.get(position).getFName());
intent.putExtra("LName_Key", listItems.get(position).getLName());
intent.putExtra("Date_Key", listItems.get(position).getDate());
intent.putExtra("Content_Key", listItems.get(position).getContent());
startActivity(intent);
}
@Override
public void onListLongClick(View v, int position) {
}
}));
//Initializing our list
listItems = new ArrayList<>();
requestQueue = Volley.newRequestQueue(this);
//Calling method to get data to fetch data
if (checkPlayServices()) {
registerGCM();
getData();
}
//initializing our adapter
adapter = new CardAdapter(listItems, this);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
}
/**
* Handles new push notification
*/
private void handlePushNotification(Intent intent) {
int type = intent.getIntExtra("type", -1);
// if the push is of chat room message
// simply update the UI unread messages count
if (type == Config.PUSH_TYPE_CHATROOM) {
ListComment listComment = (ListComment) intent.getSerializableExtra("CommentContent");
String chatRoomId = intent.getStringExtra("TimelineId");
if (listComment != null && chatRoomId != null) {
updateRow(chatRoomId, listComment);
}
} else if (type == Config.PUSH_TYPE_USER) {
// push belongs to user alone
// just showing the message in a toast
ListComment listComment = (ListComment) intent.getSerializableExtra("CommentContent");
Toast.makeText(getApplicationContext(), "New push: " + listComment.getCommentContent(), Toast.LENGTH_LONG).show();
}
}
private void updateRow(String chatRoomId, ListComment listComment) {
for (ListItem cr : listItems) {
if (cr.getId().equals(chatRoomId)) {
int index = listItems.indexOf(cr);
cr.setLastMessage(listComment.getCommentContent());
cr.setUnreadCount(cr.getUnreadCount() + 1);
listItems.remove(index);
listItems.add(index, cr);
break;
}
}
adapter.notifyDataSetChanged();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
drawerLayout.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
private JsonArrayRequest getDataFromServer() {
//JsonArrayRequest of volley
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(EndPoints.TIMELINES,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
//Calling method parseData to parse the json response
parseData(response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ActivityDashboard.this, "No More Items Available", Toast.LENGTH_SHORT).show();
}
});
return jsonArrayRequest;
}
//This method will get data from the web api
private void getData() {
//Adding the method to the queue by calling the method getDataFromServer
requestQueue.add(getDataFromServer());
}
//This method will parse json data
private void parseData(JSONArray array) {
for (int i = 0; i < array.length(); i++) {
//Creating the superhero object
ListItem listItem = new ListItem();
JSONObject json = null;
try {
//Getting json
json = array.getJSONObject(i);
//Adding data to the superhero object
listItem.setId(json.getString(TAG_ID));
listItem.setImageUrl(json.getString(TAG_IMAGE_URL));
listItem.setTitle(json.getString(TAG_TITLE));
listItem.setFName(json.getString(TAG_FNAME));
listItem.setLName(json.getString(TAG_LNAME));
listItem.setContent(json.getString(TAG_CONTENT));
listItem.setDate(json.getString(TAG_DATE));
} catch (JSONException e) {
e.printStackTrace();
}
//Adding the superhero object to the list
listItems.add(listItem);
}
//Notifying the adapter that data has been added or changed
adapter.notifyDataSetChanged();
subscribeToAllTopics();
}
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector mGestureDetector;
private ClickListener mClickListener;
public RecyclerTouchListener(final Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.mClickListener = clickListener;
mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(),e.getY());
if (child!=null && clickListener!=null){
clickListener.onListLongClick(child, recyclerView.getChildAdapterPosition(child));
}
super.onLongPress(e);
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child!=null && mClickListener!=null && mGestureDetector.onTouchEvent(e)){
mClickListener.onListClick(child, rv.getChildAdapterPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
public void gotoAdd(View view) {
Intent intent = new Intent(this, ActivityAddPost.class);
Log.e("aspirasi", "change activity");
startActivity(intent);
}
// subscribing to global topic
private void subscribeToGlobalTopic() {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra(GcmIntentService.KEY, GcmIntentService.SUBSCRIBE);
intent.putExtra(GcmIntentService.TOPIC, Config.TOPIC_GLOBAL);
startService(intent);
}
// Subscribing to all chat room topics
// each topic name starts with `topic_` followed by the ID of the chat room
// Ex: topic_1, topic_2
private void subscribeToAllTopics() {
for (ListItem cr : listItems) {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra(GcmIntentService.KEY, GcmIntentService.SUBSCRIBE);
intent.putExtra(GcmIntentService.TOPIC, "topic_" + cr.getId());
startService(intent);
}
}
@Override
protected void onResume() {
super.onResume();
// register GCM registration complete receiver
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.REGISTRATION_COMPLETE));
// register new push message receiver
// by doing this, the activity will be notified each time a new message arrives
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Config.PUSH_NOTIFICATION));
}
@Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
super.onPause();
}
// starting the service to register with GCM
private void registerGCM() {
Intent intent = new Intent(this, GcmIntentService.class);
intent.putExtra("key", "register");
startService(intent);
}
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
Log.i(TAG, "This device is not supported. Google Play Services not installed!");
Toast.makeText(getApplicationContext(), "This device is not supported. Google Play Services not installed!", Toast.LENGTH_LONG).show();
finish();
}
return false;
}
return true;
}
@Override
public void onStop() {
super.onStop();
}
public static interface ClickListener{
public void onListClick(View v, int position);
public void onListLongClick(View v, int position);
}
@Override
public void onBackPressed() {
if (exit) {
finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.", Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
}
// Before 2.0
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (exit) {
finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.", Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
return true;
}
return super.onKeyUp(keyCode, event);
}
最佳答案
这个问题是由于变量没有被实例化。您正在将该 Activity 用作 Context
太早了。你需要等到 onCreate()
或稍后在 activity lifecycle .你不能调用 getApplicationContext()
直到调用 onCreate()
之后。到那时,Activity 还没有完全初始化。
关于java - Gcm Intent Service 在 Gcm pubsub 获取空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36855075/
我想我理解 GCM 的新 notification_key 功能背后的基本原理是“只需将消息发送给用户并且只让他们阅读一次”。我从文档的这一部分推断出来: With user notification
我实现了网络推送通知。获取错误的步骤: 打开网站 订阅推送通知 通过 gcm 发送许多推送 - 一切正常 关闭网站标签 发送推送和接收“双推送”- 第一个正常,第二个是“此站点已在后台更新” 重新打开
我正在手机上测试 GCM。 (2.3.6 安卓). list 文件(MainActivity、First 和 Second Activity 不执行任何操作,它们用于其他一些测试目的,不干扰 GCM)
首先,我是 iOS 开发的新手,也是 swift 的新手。我正在尝试让适用于 iOS 的谷歌云消息传递示例。 我已经从 https://developers.google.com/cloud-mess
你们中的任何人都可以提供 GCM 推送通知的代码,其中消息从移动设备推送到 GCM 服务器。我已经从 GCM 服务器到移动设备及其工作进行了操作,但我不知道反之亦然如何操作。任何人都可以提供帮助吗?谢
我们有两个不同的应用程序,但都需要来自 Google Cloud Messages 的相同推送通知,并且我在两个应用程序中只使用了一个发件人 ID(启用 Google 控制台之一的项目编号)。 这样做
我有一个广播接收器,当应用程序打开并在后台时,它会检测即将到来的通知,但当最近的应用程序被清除时,接收器无法工作,请给我建议。 public class GcmBroadcastReceiver ex
我想从我的应用程序向 GCM 服务器发送一个心跳信号,以便连接保持有效。 我该怎么做,我怎么知道我的 GCM 服务器的 URL? 提前致谢! 最佳答案 如何发送心跳 这个类可以发送正确的 Intent
新的 GCM 3.0 应该允许 GCM 自动显示从服务器发送的通知,如果它们包含 notification 参数。 如 docs 中所述: The notification parameter wit
这个问题在这里已经有了答案: Do I need to migrate GCM to FCM on client side? (2 个答案) 关闭 3 年前。 Google 已于 2018 年 4
我遇到了 GCM 推送通知无法正确到达 Android 设备的问题。经过几天的研究,我发现 Android 设备使用心跳来保持与 GCM 服务的连接。遗憾的是,心跳似乎太高了,因此 Android 设
阅读堆栈溢出 2 天后我做了什么: 问题关键字:“Apple-Mach-O 链接器错误”、“libGcmLib.a(GCMRmqManager.o) ", sqlite3", "GCMRmq2Pers
我已经从 GCM 订阅了主题,当我通过 Android 设置删除所有应用程序数据时,GCM token 是相同的,关于主题的 GCM 通知仍然可用,所以我收到了我不想收到的通知。 我的问题是: 如何从
由于 gcm 已弃用,我们希望迁移我们的代码。正如在谷歌的迁移指南中提到的那样,对于我们的服务器应用程序,应该只需要将端点从 gcm 更改为 fcm。应用迁移已成功完成。 我们现在使用的是 com.g
这只发生在我的 Kyocera Rise 上。我有一个依赖 GCM 在手机之间进行通信的应用程序。我的 Nexus 4 和我的 HTC One X 之间的通信工作正常,每当我发送推送通知时,两部手机都
我遇到了与 this 相同的问题.我会尝试提供更多信息。 我正在使用 Play Framework,用 Java 编写。我写了一个叫做 PushNotificationQueue 的插件。 PushN
我需要在我的应用程序中接收来自不同发件人的推送通知。会成功吗? 最佳答案 你的问题的答案是是! 根据 GCM 的官方文档,您的应用可以接收来自多个发件人的消息(限制为 100 个不同的发件人),并且您
我有一个使用 GCM 推送通知的应用程序。它工作正常,我的设备注册并接收推送消息。 如果我从我的设备上卸载该应用程序,我将不再像您期望的那样收到消息。在我卸载应用程序后,您在服务器上发送消息的文本框仍
我正在处理另一个开发人员的现有项目,我需要获取 PubNub 设置的 GCM 服务器 key ,因为它被意外删除了。 有什么方法可以从 Google 设置中检索它?我在凭据和项目设置中找不到它。 我暂
嘿,我在调用 `subscribeToTopicP 类时遇到了一些 Gcm Intent 服务的问题,总是出现空指针异常。 这是我的代码: GcmIntentService.java private
我是一名优秀的程序员,十分优秀!