服务上下文不能用作ApplicationContext

时间:2014-12-17 17:52:41

标签: android

我有一个WakefulBroadcastReceiver,用于捕获Google Cloud Messages并启动IntentService来处理传入的消息。在IntentService中,我需要访问单例SQLite数据库。通常,我使用getApplicationContext()从Activity打开数据库,但是当从IntentService打开时,它会抛出错误并提供NPE。如果应用程序已经长时间背景化,当消息到达并且目标服务需要访问数据库时,它会崩溃。如果该应用程序刚刚被后台化,则可以访问该数据库 一切正常。

我的问题是:

我应该传递什么上下文以确保数据库正确打开?由于IntentService是Context的子类,我尝试传入'this',传入BaseContext()甚至ApplicationContext()。

WakefulBroadcastReceiver

@Override
public void onReceive(Context context, Intent intent) {
    // Explicitly specify that GcmIntentService will handle the intent.
    ComponentName comp = new ComponentName(context.getPackageName(),
            GcmIntentService.class.getName());
    // Start the service, keeping the device awake while it is launching.
    startWakefulService(context, (intent.setComponent(comp)));

    Log.i("Receiver", "Getting Data: "+intent.toString());
    setResultCode(Activity.RESULT_OK);
}

IntentService

public class GcmIntentService extends IntentService {
public static final String TAG = "GcmIntentService";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
private static triDbAdapter mDbHelper;
private final static String GAME_ID = "game_id=";
private static OnActiveGameNotifyListener listener = null;
private static int currentUserId;
private static String currentUserName;

public GcmIntentService() {
    super("GcmIntentService");
    mDbHelper = new triDbAdapter(this.getBaseContext());
    mDbHelper.open();                                     //   <-- Fails here


   // depending on what the Intent contains, I need to send notifications that include 
   // various items from thte database when the notification is created.  I need to know
   // the opponent's name, the score, etc. so the notification can say "Joe scored..."
    currentUserId = mDbHelper.getUserId();    
    currentUserName = mDbHelper.getName();
}

@Override
protected void onHandleIntent(Intent intent) {
<snip>
}

数据库

 public static class DatabaseHelper extends SQLiteOpenHelper {

        private static DatabaseHelper mInstance = null;

        public static DatabaseHelper getInstance(Context ctx) {

            // Use the application context, which will ensure that you
            // don't accidentally leak an Activity's context.
            // See this article for more information: http://bit.ly/6LRzfx
            if (mInstance == null) {
              mInstance = new DatabaseHelper(ctx.getApplicationContext()); // <-- fail here
            }
            return mInstance;
        }

        /**
         * Constructor should be private to prevent direct instantiation.
         * make call to static factory method "getInstance()" instead.
        */
        private DatabaseHelper(Context ctx) {
            super(ctx, DATABASE_NAME, null, DATABASE_VERSION);
        }

 /**
     * Constructor - takes the context to allow the database to be
     * opened/created
     * 
     * @param ctx the Context within which to work
     */
    public  triDbAdapter(Context ctx) {
        this.mCtx = ctx;
    }

 public triDbAdapter open() throws SQLException {
        mDbHelper = DatabaseHelper.getInstance(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

栈跟踪

    12-17 12:26:28.254    6888-6888/com.ulsanonline.triominoes I/Receiver﹕ Getting Data: Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10 pkg=com.ulsanonline.triominoes cmp=com.ulsanonline.triominoes/.GcmIntentService (has extras) }
12-17 12:26:28.264    6888-6888/com.ulsanonline.triominoes E/GcmIntentService﹕ STACKTRACE: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
            at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:267)
            at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
            at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
            at com.ulsanonline.triominoes.triDbAdapter.open(triDbAdapter.java:430)
            at com.ulsanonline.triominoes.GcmIntentService.<init>(GcmIntentService.java:57)
            at java.lang.reflect.Constructor.newInstance(Native Method)
            at java.lang.Class.newInstance(Class.java:1572)
            at android.app.ActivityThread.handleCreateService(ActivityThread.java:2713)
            at android.app.ActivityThread.access$1800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1361)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)

0 个答案:

没有答案