Android 服务上下文不能用作ApplicationContext

Android 服务上下文不能用作ApplicationContext,android,Android,我有一个WakefulBroadcastReceiver,它可以捕获Google云消息并启动IntentService来处理传入的消息。在IntentService中,我需要访问一个单例SQLite数据库。通常,我使用getApplicationContext()从活动中打开数据库,但从IntentService打开时,有时会抛出错误并给出NPE。如果应用程序已经后台运行了很长时间,当消息到达并且意图服务需要访问数据库时,它就会崩溃。如果应用程序最近刚刚被背景化,则DB是可访问的,并且 一切正常

我有一个WakefulBroadcastReceiver,它可以捕获Google云消息并启动IntentService来处理传入的消息。在IntentService中,我需要访问一个单例SQLite数据库。通常,我使用getApplicationContext()从活动中打开数据库,但从IntentService打开时,有时会抛出错误并给出NPE。如果应用程序已经后台运行了很长时间,当消息到达并且意图服务需要访问数据库时,它就会崩溃。如果应用程序最近刚刚被背景化,则DB是可访问的,并且 一切正常

我的问题是:

我应该传递什么上下文来确保数据库被正确打开?由于IntentService是Context的一个子类,我尝试只传入“this”,传入BaseContext()甚至ApplicationContext()

唤醒广播接收机 意向服务
公共类gcminentservice扩展了IntentService{
公共静态最终字符串TAG=“gcminentservice”;
公共静态最终整数通知_ID=1;
私人通知经理通知经理;
通知建筑商;
专用静态triDbAdapter mDbHelper;
私有最终静态字符串GAME_ID=“GAME_ID=”;
私有静态OnActiveGameNotifyListener侦听器=null;
私有静态int currentUserId;
私有静态字符串currentUserName;
公共GCMinentService(){
超级(“GCMinentService”);
mDbHelper=newTridBAdapter(this.getBaseContext());

mDbHelper.open();//您会遇到什么错误?您是否在任何地方关闭数据库?“如果应用程序已被后台关闭很长时间,当消息到达并且意图服务需要访问数据库时,它会崩溃”——很可能,您的进程在“很长时间”内终止。“我应该传递什么上下文以确保数据库被正确打开?”--我会使用
getApplicationContext()
,以防任何
SQLite*
类保留上下文,这样您就不会泄漏它。除此之外,我会指出“此处失败”“很好,我们真的需要堆栈跟踪。事实证明,我在哪里工作会有所不同。当我将数据库打开的内容放入构造函数时,如果应用程序不再运行且在“最近”中不可见,则在收到消息时失败。然而,如果我在onHandleIntent()中打开数据库并取出我需要的内容,然后一切都很好。我可以关闭后台应用程序,当接收者收到新的消息时,OnHandleContent似乎对上下文有不同的想法。知道为什么会这样吗?
@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);
}
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)