Как зарегистрировать BroadcastReceiver без активности для виджета приложения? - PullRequest
0 голосов
/ 19 марта 2020

Я создал виджет приложения, который просто извлекает данные через равные промежутки времени, поэтому он не выполняет никаких действий; даже не конфиг деятельности. Можно ли зарегистрировать приемник вещания, используя следующий код, без использования действия?

context.registerReceiver(networkChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

По сути, я хочу, чтобы виджет автоматически обновлял sh всякий раз, когда устройство подключалось к сети вместо ожидания для следующего refre sh.

я пытался сделать это в методах onEnabled () и onUpdate () AppWidgetProvider, но он выдает android.content.ReceiverCallNotAllowedException, поэтому я не знаю, где еще я могу это сделать .

Манифест также не поддерживается, так как ConnectivityManager.CONNECTIVITY_ACTION игнорируется SDK 24 +.

Ответы [ 2 ]

0 голосов
/ 24 марта 2020

Я попытался использовать Сервис для решения моей проблемы, но, как указал HeyAlex, Сервисы работают по-разному в Oreo v8.0 + из Android и требуют, чтобы у вас появилось уведомление, которое очень неприглядно с точки зрения пользовательского интерфейса .

После некоторых дальнейших исследований я обнаружил отдельный поток Stackoverflow, касающийся этих изменений:

Android 8.0: java .lang.IllegalStateException: не разрешено запускать службу. Намерение

Возможно, это не лучшее решение, поскольку оно устарело и больше не поддерживается, но JobServiceIntent работает с Oreo и имеет обратную совместимость. Вам понадобятся следующие разрешения в манифесте:

<!-- < 8.0 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- >= 8.0, inside application -->
        <service
            android:name="com.example.ListenerService"
            android:permission="android.permission.BIND_JOB_SERVICE" />

Затем мой сервис расширяет JobIntentService вместо Service, и все это работает; сетевой прослушиватель настраивается без необходимости каких-либо действий и без уведомления о Android 8 +.

public class ListenerService extends JobIntentService {

    public static final int JOB_ID = 1;

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
         getApplicationContext().registerReceiver(networkChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

    }

    public static void enqueueWork(Context context, Intent intent) {
        ListenerService.context = context;
        enqueueWork(context, ListenerService.class, JOB_ID, intent);
    }

    private static final BroadcastReceiver networkChangeReceiver = new BroadcastReceiver() {
        // usual broadcast methods in here such as onReceive
    }

}

Услуга может быть запущена с помощью:

ListenerService.enqueueWork(context,intent);
0 голосов
/ 24 марта 2020

Прежде всего, давайте определим жизненный цикл приложений. AppWidgetProvider по умолчанию BroadcastReceiver , поэтому он может работать в течение короткого времени ( onReceive () имеет 10-секундный таймаут - так что onUpdate () и onEnabled () и все другие обратные вызовы AppWidgetProvider будут выполняться при обратном вызове onReceive ()). Таким образом, невозможно зарегистрировать динамический приемник c. У вас есть только один вариант (поскольку у вас нет активности, и вы хотите обновить свой виджет без пользовательского интерфейса) - сервис переднего плана (да, вам нужно уведомление для устройств oreo +, но где нет других способов). Вы можете зарегистрировать свой приемник и обновить его на ConnectivityManager.CONNECTIVITY_ACTION и обновить виджет, например:

val intent = Intent(this, YourAppWidgetProvider::class.java)
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
val ids = AppWidgetManager.getInstance(application).getAppWidgetIds(ComponentName(getApplicationContext(), YourAppWidgetProvider::class.java)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
sendBroadcast(intent)

И в вашем случае это единственный способ обновить виджет, если вам нужно реагировать на динамику c действие получателя.

...