【问题标题】:How can a closed application receive periodic broadcasts?封闭的应用程序如何接收定期广播?
【发布时间】:2020-12-29 22:04:24
【问题描述】:

我有一台装有 Android 9 的设备,我正在开发一个根据当前日期和时间显示内容的应用程序。我希望它定期检查是否有新内容可用并通知用户。此外,当用户关闭应用程序时,我希望它也能正常工作。例如,我的电子邮件应用程序在关闭时也会显示有关新电子邮件的通知。

我的方法是接收一般广播(Intent.ACTION_USER_PRESENTIntent.ACTION_SCREEN_ON),在接收时运行计时器,然后定期检查新内容。我知道用户必须为此启动我的应用程序一次 (Broadcast receiver not working in ICS if the app is not started atleast once)。如果用户使用多任务按钮并向上滑动我的活动以将其关闭,则该方法成功。

即使用户关闭了我的应用程序/活动,我如何才能接收广播。

这里有很多个帖子,问的都是一样的,但大部分似乎都已经过时了!我已经尝试了很多,但我没有设法让它工作!因此,我为 API 28 设置了一个示例应用程序,我想再次提出这个问题,但这次是一个已定义的示例。那么应该很容易检查所提出的解决方案是否真的有效!

  1. AndroidStudio 中使用File->New->New Project...->Empty Activity->Language: Java, SDK: API 28 创建一个空活动。
  2. 添加类MyBroadcastReceiver,内容如下:
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. 修改MainActivity类,使其内容如下:
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);
        }
    }
}

在安装和运行 Activity 时,每当我注销并再次登录时,我都会看到 toast。但是,一旦我向上滑动活动以关闭它,我就再也看不到吐司了。我该如何改变呢?

【问题讨论】:

    标签: java android broadcastreceiver


    【解决方案1】:

    但是,一旦我向上滑动活动以关闭它,我就再也看不到吐司了。

    当然。充其量,您的接收器将在您的进程运行时接收广播。您的进程将因多种原因被终止,包括您所描述的手动用户操作。

    我该如何改变呢?

    对于较旧的 Android 设备,您可以通过 <receiver> 元素在清单中注册您的接收器。这不适用于大多数implicit broadcasts on Android 8.0 及更高版本,例如您引用的两个。

    例如,我的电子邮件应用程序在关闭时也会显示有关新电子邮件的通知。

    服务器可能正在使用 Firebase 云消息传递 (FCM) 来提醒应用有新消息。或者,该应用程序可以使用WorkManager 或类似的方式进行轮询。请记住,打盹模式、应用待机和各种制造商特定的黑客攻击使应用难以在后台可靠地执行定期工作,因为此类工作不利于电池寿命。

    【讨论】:

    • 我能否以某种方式注册我的活动以收到警报,例如,如果 WhatsApp 消息到达?我也会看看WorkManager ...
    • @BenjaminBihler:“我能否以某种方式注册我的活动以收到警报,例如,如果 WhatsApp 消息到达?” -- 您需要询问 WhatsApp。我没有听说他们有 API,虽然我没有太注意它,所以可能错过了。
    • 我已经试过了!它与WorkManager 一样工作。非常感谢!!!
    【解决方案2】:

    正如对已接受答案的评论中所述,使用WorkManager 是解决我的问题的简单方法。另外,我想在这里向对同一主题感兴趣的任何人展示我的代码。

    班级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();
        }
    }
    
    

    班级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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      相关资源
      最近更新 更多