Gcm Intent Service在Gcm pubsub上获取空指针异常

时间:2016-04-26 04:05:44

标签: java android google-cloud-messaging

嘿我在调用`subscribeToTopicP类时遇到Gcm意图服务的问题,总是得到空指针异常。

这是我的代码:

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);
}

1 个答案:

答案 0 :(得分:2)

此问题是由于未实例化的变量。您过早地将活动用作Context。您需要等到onCreate()中的activity lifecycle或更晚。在调用onCreate()之前,您无法致电getApplicationContext()。直到那时,活动才完全初始化。