Android:报警管理器;从 Broadcastreceiver 访问 MainActivity 中的 SQLiteOpenhelper 时出现 Nullpointer class

Android: Alarm Manager; Nullpointer when accessing SQLiteOpenhelper in MainActivity from Broadcastreceiver class

我正忙于开发一个报价应用程序,该应用程序每天早上都会在 9:00am 向用户显示新的励志名言。

我的 MainActivity 中有这个方法可以在显示单引号的 listView 中提取和显示引号。我知道存在此类问题的其他示例,但我没有看到一个使用数据库数据和游标或游标适配器的示例。

public void DailyQuoteDatabaseAccess(){

    SQLiteOpenHelper sqLiteOpenHelper = new SQLiteAssetHelper(this, DATABASE_NAME, null, DATABASE_VERSION);
    SQLiteDatabase SqlDb = sqLiteOpenHelper.getReadableDatabase();
    String rawQuery = "SELECT * FROM dailyQuoteTable ORDER BY RANDOM() LIMIT 1";
    Cursor cursor = SqlDb.rawQuery(rawQuery, null);
    DailyQuoteCursorAdapter DQCursorAdapter = new DailyQuoteCursorAdapter(this, cursor);
    this.mDailyQuoteListView.setAdapter(DQCursorAdapter);
}

我是从 OnCreate 调用这个方法的,它工作得很好,但是每次重新启动应用程序时它都会重新加载。我正在使用 AlarmManager 将闹钟设置为每天早上在 9:00am 更改报价并且闹钟正在触发,但问题在于能够 运行 来自广播接收器 [=35] 我的 MainActivity 中的意图=].这是 class... 空白,因为我不知道如何让它工作。

package com.myapps.dailyquotes;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class TodaysQuoteAlarmReceiver  extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    MainActivity mainActivity = new MainActivity();
    mainActivity.DailyQuoteDatabaseAccess();

    }
}

非常感谢在此领域的任何帮助。我应该使用一个全新的意图还是一个对象 class,你能举个例子吗?

****11/22/18****

我忘了添加我的自定义游标适配器...我认为这可能会有所不同,但我仍然不确定如何将它与 Broadcast Receiver 集成以传递我需要的数据...

public class DailyQuoteCursorAdapter extends CursorAdapter{

    public DailyQuoteCursorAdapter(Context context, Cursor c) {
        super(context, c, 0);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(R.layout.daily_quote_item, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        TextView NameTextView = (TextView) view.findViewById(R.id.name);
        TextView NumberTextView = (TextView) view.findViewById(R.id.number);
        TextView DateTextView = (TextView) view.findViewById(R.id.date);
        TextView QuoteTextView = (TextView) view.findViewById(R.id.quote);

        String name = cursor.getString(cursor.getColumnIndexOrThrow("quote_main"));
        String number = cursor.getString(cursor.getColumnIndexOrThrow("number"));
        String date = cursor.getString(cursor.getColumnIndexOrThrow("date"));
        String quote = cursor.getString(cursor.getColumnIndexOrThrow("quote"));

        nameTextView.setText(name + " ");
        numberTextView.setText(String.valueOf(number) + ":");
        dateTextView.setText(String.valueOf(date));
        quoteTextView.setText(quote);

    }

}

这是我的空指针日志猫...

Process: com.myapps.dailyquotes, PID: 15024
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x4000010 (has extras) } in com.myapps.dailyquotes.TodaysQuoteAlarmReceiver@d63089d
    at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52497(LoadedApk.java:1323)
    at android.app.-$Lambda$aS31cHIhRx41653CMnd4gZqshIQ.$m(Unknown Source:4)
    at android.app.-$Lambda$aS31cHIhRx41653CMnd4gZqshIQ.run(Unknown Source:39)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
    at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:152)
    at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.<init>(SQLiteAssetHelper.java:109)
    at com.readystatesoftware.sqliteasset.SQLiteAssetHelper.<init>(SQLiteAssetHelper.java:129)
    at com.myapps.dailyquotes.MainActivity.DailyQuoteDatabaseAccess(MainActivity.java:403)
    at com.myapps.dailyquotes.TodaysQuoteAlarmReceiver.onReceive(TodaysQuoteAlarmReceiver.java:18)

接收方确实尝试 运行 来自 MainActivity 的方法,所以我知道它正在建立连接,但错误来自 MainActivity class 内 DailyQuoteDatabaseAccess 方法内的这一行:

 SQLiteOpenHelper sqLiteOpenHelper = new SQLiteAssetHelper(this, DATABASE_NAME, null, DATABASE_VERSION);

对于每日行情,我做了一些事情....

public void setAlarm() {
// Quote in Morning at 08:32:00 AM
    Calendar calendar = Calendar.getInstance();

    calendar.set(Calendar.HOUR_OF_DAY, 8);
    calendar.set(Calendar.MINUTE, 32);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    Calendar cur = Calendar.getInstance();

    if (cur.after(calendar)) {
        calendar.add(Calendar.DATE, 1);
    }

    Intent myIntent = new Intent(context, DailyReceiver.class);
    int ALARM1_ID = 10000;
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            context, ALARM1_ID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}

现在在数据库 class 中创建函数以在数据库 class

中获取随机报价
public String getAlarmQuote(int id, String table) {
   String quote = "", author = "";
   SQLiteDatabase db = this.getReadableDatabase();
   Cursor cursor = db.query(table, new String[]{QUOTE_ID, QUOTE_QUOTE, QUOTE_AUTHOR}, QUOTE_ID + "=?", new String[]{String.valueOf(id)}, null, null, null, null);
   if (cursor != null && cursor.getCount() > 0) {
       if (cursor.moveToFirst()) {
           quote = cursor.getString(cursor.getColumnIndex(QUOTE_QUOTE));
           author = cursor.getString(cursor.getColumnIndex(QUOTE_AUTHOR));
       }
   }
   db.close();
   return quote;
}

并获得这个接收器

public class DailyReceiver extends BroadcastReceiver {

DatabaseHelper databaseHelper;

@Override
public void onReceive(Context context, Intent intent) {String quote ;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context
        .getSystemService(Context.NOTIFICATION_SERVICE);

Intent notificationIntent = new Intent(context, DailySpecialActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
        notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

// get your quote here
   int max = databaseHelper.getTotalQuotes();  // here you have to put total number of quotes in your database table
   Random r = new Random();
   int randomNumber = r.nextInt(max - 1 + 1) + 1;
   quote = databaseHelper.getAlarmQuote(randomNumber, YourTableName);


NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(
        context).setSmallIcon(R.mipmap.ic_launcher)
        .setContentTitle("My Quotes")
        .setContentText(quote).setSound(alarmSound)
        .setAutoCancel(true).setWhen(when)
        .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
        .setStyle(new NotificationCompat.BigTextStyle().bigText(quote))
        .setContentIntent(pendingIntent)
        .setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});  // Declair VIBRATOR Permission in AndroidManifest.xml
notificationManager.notify(5, mNotifyBuilder.build());
   }
}

在这里当你重启你的phone你也需要重启你的闹钟,所以我已经做了

public class WakeUpAlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
    // Quote in Morning
    Calendar calendar = Calendar.getInstance();

    calendar.set(Calendar.HOUR_OF_DAY, 8);
    calendar.set(Calendar.MINUTE, 30);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    Calendar cur = Calendar.getInstance();

    if (cur.after(calendar)) {
        calendar.add(Calendar.DATE, 1);
    }
    Intent myIntent = new Intent(context, DailyReceiver.class);
    int ALARM1_ID = 10000;
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, ALARM1_ID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
  }
 }
}

你的AndroidManifest.xml

终于来了
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nils.myquotesapp">
<!--you must need this three permissions-->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />

<application
  android:name="com.nils.myquotesapp.QuotesApplication"
  android:allowBackup="true"
  android:icon="@mipmap/ic_launcher"
  android:label="@string/app_name"
  android:largeHeap="true"
  android:supportsRtl="true"
  android:theme="@style/AppTheme">
  <activity
    android:name="com.nils.myquotesapp.Activity.MainActivity"
    android:label="@string/app_name"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<receiver
    android:name="com.nils.myquotesapp.DailyReceiver"
    android:enabled="true" />

<receiver
    android:name="com.nils.myquotesapp.WakeUpAlarmReceiver"
    android:enabled="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.DEFAULT" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

</application>
<meta-data
  android:name="com.google.android.gms.version"
  android:value="@integer/google_play_services_version" />
</manifest>