我试图建立通知,但似乎我在这行NotificationCompat.BuilderNPE mNotificationManager.notify(NOTIFICATION_ID, t); -ed。

经过10个小时的研究,我解决了许多问题,包括确保我的Intent作为服务运行,上下文能够正确解析以及onCreate运行一次。
这是我的清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.willypt.himtichannelsubscribe"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission
        android:name="com.willypt.himtichannelsubscribe.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.willypt.himtichannelsubscribe.permission.C2D_MESSAGE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.willypt.himtichannelsubscribe.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver
            android:name="com.willypt.himtichannelsubscribe.GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="com.willypt.himtichannelsubscribe" />
            </intent-filter>
        </receiver>

        <service android:name="com.willypt.himtichannelsubscribe.GcmIntentService" />

        <activity
            android:name="com.willypt.himtichannelsubscribe.ChannelActivity"
            android:label="@string/title_activity_channel" >
        </activity>
    </application>

</manifest>


ParseJSON.java,我的readLink()函数是调用GcmIntentService的函数

package com.willypt.himtichannelsubscribe;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.willypt.himtichannelsubscribe.GcmIntentService;

public class ParseJSON extends Activity {

/** Called when the activity is first created. */

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    StrictMode.ThreadPolicy policy = new StrictMode.
    ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
  }
  public ArrayList<String> GetJSON(String url){
        ArrayList<String> val = new ArrayList<String>();
        String readLink = readLink(url);
        JSONArray jsonArray = new JSONArray();
        try {
          jsonArray = new JSONArray(readLink);
          for (int i = 0; i < jsonArray.length(); i++) {
              val.add(jsonArray.getString(i));
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
        return val;
  }
  public String readLink(String url) {
    StringBuilder builder = new StringBuilder();
    HttpClient client = new DefaultHttpClient();
    HttpGet httpGet = new HttpGet(url);
    Log.e(ParseJSON.class.toString(),url);
    try {
      HttpResponse response = client.execute(httpGet);
      StatusLine statusLine = response.getStatusLine();
      int statusCode = statusLine.getStatusCode();
      if (statusCode == 200) {
        HttpEntity entity = response.getEntity();
        InputStream content = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(content));
        String line;
        while ((line = reader.readLine()) != null) {
          builder.append(line);
        }
      } else {
        Log.e(ParseJSON.class.toString(), "Failed to download file");

        Intent Notif = new Intent(this, GcmIntentService.class);
        Notif.putExtra("PostThisNotifString", "Failed to download file");
        this.startService(Notif);
      }
    } catch (ClientProtocolException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return builder.toString();
  }
}


GcmIntentService.java

package com.willypt.himtichannelsubscribe;

import com.google.android.gms.gcm.GoogleCloudMessaging;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class GcmIntentService extends IntentService {
    public static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    NotificationCompat.Builder builder;
    private PendingIntent contentIntent;

    public GcmIntentService() {
        super("GcmIntentService");
    }
    public static final String TAG = "HIMTI Notification v2";
    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        // The getMessageType() intent parameter must be the intent you received
        // in your BroadcastReceiver.
        String messageType = gcm.getMessageType(intent);

        if (!extras.isEmpty()) {  // has effect of unparcelling Bundle
            /*
             * Filter messages based on message type. Since it is likely that GCM will be
             * extended in the future with new message types, just ignore any message types you're
             * not interested in, or that you don't recognize.
             */
            if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
                sendNotification("Send error: " + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
                sendNotification("Deleted messages on server: " + extras.toString());
            // If it's a regular GCM message, do some work.
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                // This loop represents the service doing some work.
                for (int i = 0; i < 5; i++) {
                    Log.i(TAG, "Working... " + (i + 1)
                            + "/5 @ " + SystemClock.elapsedRealtime());
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                    }
                }
                Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
                // Post notification of received message.
                sendNotification("Received: " + extras.toString());
                Log.i(TAG, "Received: " + extras.toString());
            } else {
                //I just need to post a simple notification to user
                String ex = intent.getStringExtra("PostThisNotifString");
                sendNotification(ex);
            }
        }
        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GcmBroadcastReceiver.completeWakefulIntent(intent);
    }

    // Put the message into a notification and post it.
    // This is just one simple example of what you might choose to do with
    // a GCM message.
    public void sendNotification(String msg) {
        Intent u = new Intent(this, MainActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, u,0);


        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
        .setContentTitle("HIMTI Broadcast")
        .setStyle(new NotificationCompat.BigTextStyle()
        .bigText(msg))
        .setContentText(msg);
        Notification t = mBuilder.build();
        mBuilder.setContentIntent(contentIntent);
        mNotificationManager.notify(NOTIFICATION_ID, t);
    }
}


这是logcat

10-13 11:45:36.429: E/AndroidRuntime(16096): FATAL EXCEPTION: IntentService[GcmIntentService]
10-13 11:45:36.429: E/AndroidRuntime(16096): java.lang.NullPointerException
10-13 11:45:36.429: E/AndroidRuntime(16096):    at com.willypt.himtichannelsubscribe.GcmIntentService.sendNotification(GcmIntentService.java:108)
10-13 11:45:36.429: E/AndroidRuntime(16096):    at com.willypt.himtichannelsubscribe.GcmIntentService.onHandleIntent(GcmIntentService.java:85)
10-13 11:45:36.429: E/AndroidRuntime(16096):    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
10-13 11:45:36.429: E/AndroidRuntime(16096):    at android.os.Handler.dispatchMessage(Handler.java:99)
10-13 11:45:36.429: E/AndroidRuntime(16096):    at android.os.Looper.loop(Looper.java:137)
10-13 11:45:36.429: E/AndroidRuntime(16096):    at android.os.HandlerThread.run(HandlerThread.java:60)

最佳答案

我的猜测:您尚未初始化mNotificationManager字段。

您的onHandleIntent()中可能需要以下内容:

if (mNotificationManager == null) {
    mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}

09-28 13:04