How can a closed application receive periodic broadcasts?

孤街醉人 提交于 2021-02-10 14:14:26

问题


I have a device with Android 9 and I am developing an application that displays content depending on the current date and time. I would like it to regularly check whether new content is available and inform the user about it. Additionally I would like that to work also when the user closes the application. My email application here for example shows notifications about new emails also when it's closed.

My approach has been to receive general broadcasts (Intent.ACTION_USER_PRESENT and Intent.ACTION_SCREEN_ON), run a timer on receiving and then check regularly for new content. I know that the user has to start my application once for that (Broadcast receiver not working in ICS if the app is not started atleast once). The approach is not successful, if the user uses the multitasking button and swipes my activity up to close it.

How can I receive broadcasts even though the user has closed my application/activity.

There are many posts here, that ask the same, but most of them seem to be outdated! I have tried so many of them, but I have not managed to get it to work! Therefore I have set up an example application for API 28 and I would like to ask the question again, but this time with a defined example. Then it should be easy to check whether the proposed solution really works!

  1. Create an empty activity in AndroidStudio with File->New->New Project...->Empty Activity->Language: Java, SDK: API 28.
  2. Add a class MyBroadcastReceiver with the following content:
package org.test.myapplication;

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

public class MyBroadcastReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Toast.makeText(context, "Hurray! I have received the broadcast!", Toast.LENGTH_LONG).show();
    }
}
  1. Modify the class MainActivity to have the following content:
package org.test.myapplication;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity
{
    private static BroadcastReceiver broadcastReceiver = null;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (null == broadcastReceiver)
        {
            // Register broadcast receiver (only a running application my do that)
            IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
            filter.addAction(Intent.ACTION_SCREEN_ON);

            Log.i("MainActivity", "Registered broadcast receiver.");

            broadcastReceiver = new MyBroadcastReceiver();

            registerReceiver(broadcastReceiver, filter);
        }
    }
}

When installing and running the activity, I see the toast whenever I log off and on again. But as soon as I have swiped the activity up to close it, I don't see the toast anymore. How can I change that?


回答1:


But as soon as I have swiped the activity up to close it, I don't see the toast anymore.

Sure. At best, your receiver will receive broadcasts while your process is running. Your process will be terminated for lots of reasons, including manual user action as you describe.

How can I change that?

For older Android devices, you would register your receiver in the manifest, via a <receiver> element. That will not work for most implicit broadcasts on Android 8.0 and higher, such as the two that you cited.

My email application here for example shows notifications about new emails also when it's closed.

The server could be using Firebase Cloud Messaging (FCM) to alert the app of new messages. Alternatively, the app could be polling using WorkManager or something similar. Bear in mind that Doze mode, app standby, and a wide range of manufacturer-specific hacks make it difficult for apps to reliably do periodic work in the background, as such work is bad for battery life.




回答2:


As stated in a comment to the accepted answer, using WorkManager is an easy solution for my problem. As an addition I would like to show my code here for anyone who is interested in the same topic.

Class MyWorker:

package org.test.myapplication;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class MyWorker extends Worker
{
    public MyWorker(@NonNull Context context, @NonNull WorkerParameters params)
    {
        super(context, params);
    }

    @Override
    public Result doWork()
    {
        Handler handler = new Handler(Looper.getMainLooper());
        handler.postDelayed(new Runnable()
        {
            @Override
            public void run()
            {
                // Run your task here
                Toast.makeText(getApplicationContext(), "Testing", Toast.LENGTH_SHORT).show();
            }
        }, 1000);

        // Indicate whether the work finished successfully with the Result
        return Result.success();
    }
}

Class MainActivity:

package org.test.myapplication;

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import androidx.work.WorkRequest;

import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WorkRequest workRequest =
                new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES).build();

        WorkManager.getInstance(this).enqueue(workRequest);
    }
}


来源:https://stackoverflow.com/questions/65479482/how-can-a-closed-application-receive-periodic-broadcasts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!