【问题标题】:Android broadcastreceiver not triggering when app is not running应用程序未运行时Android广播接收器未触发
【发布时间】:2017-01-20 15:12:19
【问题描述】:

按照本指南https://developer.android.com/training/monitoring-device-state/battery-monitoring.html

我制作了一个接收器,每次插入或拔出充电器时,它都会将电池信息记录到文件中。 Activity 读取该文件的内容并将其显示在屏幕上。无论应用程序运行如何,这都应该始终有效,但事实并非如此。它仅在应用程序打开/在内存中时注册,当我清除内存或重新启动它停止工作时。

清单:

  <receiver android:name=".Receiver">
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
        </intent-filter>
    </receiver>

接收者:

public class Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
      Intent chargingIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
      final int status = chargingIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
      int level = chargingIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
      int plugged = chargingIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
      Battery battery = new Battery();
      battery.setLevel(level);
      battery.setDate(new Date());
      battery.setPlugged(plugged);
      battery.setStatus(status);
      Logger.log(JSON.toJSONString(battery));
    }
}

记录器

public class Logger {

public static void log(String text)
{
    File logFile = new File(Environment.getExternalStorageDirectory().getPath()+"/batterylog.txt");
    Log.d("files"," logfile "+logFile+": "+logFile.exists());

    if (!logFile.exists())
    {
        try
        {
            logFile.createNewFile();
            Log.d("files","new logfile created"+logFile);
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    try
    {
        //BufferedWriter for performance, true to set append to file flag
        BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
        buf.append(text).append("\r\n");
        buf.flush();
        buf.close();
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

这是在应用打开时拔掉电源后的样子:

如果不是,它只是空的。

【问题讨论】:

  • 你需要注册一个在后台监听这个广播的服务。
  • @ditn 我正在关注本指南:developer.android.com/training/monitoring-device-state/…,它说即使应用程序关闭,BroadcastReceiver 也应该触发。不是这样吗?
  • onReceive 肯定会在上面的代码中被调用,无论应用程序是否运行。您可以在您的onReceive 中添加一个简单的Log.i 声明以确认相同。我想问题出在您的另一段代码中。你能说出Battery类是什么吗?它当然不是 Android 框架提供的类。此外,Logger 类中没有您在代码中提到的方式的 Logger.log API。这些是您的自定义课程吗?另外,您如何测试此代码?我的意思是你怎么知道上面的行不通?
  • @Asalas77 我注意到很少有设备存在这个问题。当我尝试在“Lenovo A 600PLUS”上运行我的应用程序时,我遇到了同样的问题,但它不起作用,同一个应用程序在其他设备上运行良好。
  • @JithishPN 不,我认为这是我的操作系统或设备的软件限制,因此暂时搁置了这个应用程序。我正在运行 MIUI 8,这是一个经过大量修改的 Android 7,很多东西在普通 Android 上的工作方式都不同。

标签: android broadcastreceiver batterymanager


【解决方案1】:

尝试将android:enabled="true" 设置为您的接收者

这样

 <receiver android:name=".Receiver"
    android:enabled="true">
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
        </intent-filter>
    </receiver>

更新

我刚刚以你的方式在我的应用程序中实现了它,并且它有效。但是我用right click-&gt;new-&gt;other-&gt;broadcast receiver做到了

插入意图过滤器后,我得到了这样的代码

    <receiver
        android:name=".MyReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
        </intent-filter>
    </receiver>

它实际上调用了onReceive方法

【讨论】:

  • 添加了exported 属性,但仍然没有变化。根据文档似乎也不相关
  • 尝试用Android Studio helper再次添加(右键文件等)
  • 做到了,唯一显着的区别是接收器中的空结构,但仍然没有变化。从管理器重新启动或关闭应用程序后不会触发
【解决方案2】:

您是否尝试过使用唤醒锁?通常应用程序会在接收到广播时唤醒,但如果没有(在少数设备中发生),则尝试使用唤醒锁,这将强制唤醒设备。

如何使用唤醒锁:

//注册唤醒锁

if (mWakeLock == null) {
        PowerManager pm = (PowerManager)yourcontext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, yourcontext);
        mWakeLock.setReferenceCounted(false);

}

//使用acquire应用唤醒锁

mWakeLock.acquire();

【讨论】:

  • 我把这段代码放在哪里?在我的接收器或活动中?
  • 广播意图收到了吗?由于未收到广播,因此您必须将其置于活动状态。
  • 这也无济于事,它现在很受欢迎。有时有效,大部分时间无效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
相关资源
最近更新 更多