Когда мое приложение не работает (только когда оно не запущено), почему мой BroadcastReceiver выдает мне исключение nullpointer? - PullRequest
0 голосов
/ 20 декабря 2011

Я постараюсь подвести итог просто потому, что мой оригинальный код длинный. Предположим, что мой приемник вещания выглядит так:

public class SMSBroadcastReceiver extends BroadcastReceiver {

    static ArrayList<String> phonenumber_array = new ArrayList<String>();
    static ArrayList<String> message_array = new ArrayList<String>();

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

        Bundle bundle = intent.getExtras();

        if (bundle != null) {

        Object[] pdus = (Object[]) bundle.get("pdus");
        SmsMessage[] sms = new SmsMessage[pdus.length];

        for (int i = 0; i < sms.length; i++) {

        sms[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);

           phonenumber_array.add(0,sms[i].getOriginatingAddress());
           message_array.add(0,sms[i].getMessageBody());

           com.test.ListActivityClass.myadapter.notifyDataSetChanged();
       }
}

В моем AndroidManifest.xml у BroadcastReceiver есть фильтр IntentFilter "android.provider.Telephony.SMS_RECEIVED".

Мой ListActivityClass расширяет ListActivity, содержит myadapter, который представляет собой ArrayAdapter, например: myadapter = new CustomAdapter (this, com.test.SMSBroadcastReceiver.phonenumber_array, com.test.SMSBroadcastReceiver.message_array)

Итак, моя проблема: я посылаю смс из затмения в эмулятор. всякий раз, когда myadapter.notifyDataSetChanged (); вызывается в моем BroadcastReceiver, когда мое приложение не запущено (полностью остановлено, процесс не запущен, нет действий), я получаю исключение nullpointer.

Когда я удаляю myadapter.notifyDataSetChanged (); проблема исчезла.

Когда приложение запущено, проблем также нет, мое приложение правильно получает новые полученные смс и отображает их в списке.

Так что мое предположение было = Когда приложение работает, BroadcastReceiver может обнаружить myadapter, потому что приложение находится в памяти, поэтому оно может уведомлять об изменениях. когда приложение не запущено, оно не находится в памяти, поэтому BroadcastReceiver не может видеть какой-либо myadapter, поэтому оно выдает исключение nullpointer. это имеет смысл. Поэтому я попытался проверить: находится ли процесс в памяти, уведомлять об изменениях, в противном случае не уведомлять (потому что мои приложения получают все смс, полученные onCreate (), поэтому в этом нет необходимости.

ActivityManager activityManager = (ActivityManager) context
    .getSystemService(context.ACTIVITY_SERVICE);
    List<RunningAppProcessInfo> runningProcInfo = activityManager
    .getRunningAppProcesses(); for (int i1 = 0; i1 <
    runningProcInfo.size(); i1++) { 

    if (runningProcInfo.get(i1).processName.equals("com.test")) {
            com.test.ListActivityClass.myadapter.notifyDataSetChanged();
    }

Но ничего не изменилось. У меня все еще есть исключение nullpointer, когда приложение не запущено.

Хуже всего то, что я попытался заменить phonenumber_array на phonenumber_array.add (0, "somephonenumber"); и message_array.add (0, "somemessage"); чтобы проверить, работает ли BroadcastReceiver в фоновом режиме, даже если приложение закрыто, мои мысли были правильными. После исключения нулевого указателя я запустил приложение, и присутствовали somephonenumber и somemessage.

Что мне не хватает? BroadcastReceiver работает в фоновом режиме или только при запуске приложения? что случилось?

Ответы [ 2 ]

1 голос
/ 20 декабря 2011

Во-первых, члены статических данных (и замена, предложенная в комментариях, Application) живут только в течение всего процесса.Ваш процесс может уйти на микросекунды после завершения onReceive().

Если вы хотите использовать элементы статических данных в качестве кэша, это нормально, но надежные данные должны храниться в файловой системе (базе данных, плоском файле и т. Д.).).

Во-вторых, myadapter не должен быть статическим элементом данных.Вы теряете память.

Либо:

  • Переместите этот BroadcastReceiver, чтобы быть зарегистрированным действием с помощью registerReceiver(), или

  • Пусть этот BroadcastReceiver отправит другую упорядоченную трансляцию, которая будет передана текущей деятельностью (если она находится на переднем плане), как описано в в этом сообщении в блоге и продемонстрировано в этот пример проекта

0 голосов
/ 20 декабря 2011

Вы можете создать статическую логическую переменную onScreen и задать для нее true в методе onResume, а также установить false в методе onPause. Это самый простой способ понять, находится ли приложение на экране

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...