标签: android-broadcastreceiver

BroadcastReCeiver 内部实现

我试图了解广播接收器在内部是如何工作的。

当我调用registerReceiver()方法时,内部会发生什么?它是否在内部创建服务?

当我打电话时,内部会发生什么sendBroadcast

如果我必须实现我自己的BroadcastReceiver类(不扩展 AndroidBroadcastReceiver类),我该如何实现?

我做了很多研究,但我只找到了BroadcastReceiver工作原理。我也查看了 Android 源代码以了解其工作原理,但也无济于事。

android broadcastreceiver android-service intentservice android-broadcastreceiver

5
推荐指数
1
解决办法
926
查看次数

如何使用 MediaSession.setMediaButtonReceiver(PendingIntent) 恢复播放

当我的应用程序停止时单击耳机按钮时,我试图能够从我的应用程序开始播放音乐。

我可以使用MediaSession.CallbackonMediaButtonEvent()或者现在已经过时registerMediaButtonEventReceiver()监听媒体按钮点击WHILE我的应用程序在播放音乐,但如果我暂停音乐一分钟,我的活动和播放服务仍在运行,然后我按下耳机按钮,我看到我已经失去了接收媒体按钮广播的能力。相反,Google 即时会打开。

我正在尝试做的是像 Google Play Music 这样的东西。即使应用程序完全停止,它也可以开始播放音乐......后台没有服务。

我觉得setMediaButtonReceiver()是用来做这个的,但我一直无法让它工作。

setMediaButtonReceiver(PendingIntent mbr)

为您的媒体按钮接收器设置一个挂起的意图,以允许在会话停止后重新开始播放。如果您的应用以这种方式启动,将通过待处理的意图发送 ACTION_MEDIA_BUTTON 意图。

我的服务中有以下代码段。

PendingIntent pi = PendingIntent.getBroadcast(HeadsetService.this, 0, new Intent(HeadsetService.this, RemoteControlReceiver.class), 0);
mMediaSession.setMediaButtonReceiver(pi);
Run Code Online (Sandbox Code Playgroud)

我的 RemoteControlReceiver BroadcastReceiver 已在清单中注册,但是当我按下按钮时我没有收到广播。

我还看到其他音乐播放器应用在停止播放大约一分钟后就失去了接收媒体按钮广播的能力。

有什么想法可以让我拥有更强大的媒体按钮控件吗?

提前致谢!

android android-mediaplayer android-audiomanager android-broadcastreceiver android-mediasession

5
推荐指数
1
解决办法
1927
查看次数

如何区分USB和SD卡口?

我有一部 Android 6.0 手机,配有内部存储器、可移动 SD 卡和插入手机中的 USB OTG(带微型 USB 插孔的笔式驱动器)。Android设备中弹出可移动SD卡和USB OTG:“设置”->“存储和USB”。我可以在该设备中安装可移动SD卡和USB OTG。例如,我安装了可移动 SD,并希望将此事件与 USB OTG 的安装区分开来。我可以在接收器中执行的唯一操作

    <receiver
        android:name=".receiver.RemovableMediaReceiver"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
        </intent-filter>

        <intent-filter>
            <action android:name="android.intent.action.MEDIA_MOUNTED"/>
            <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
            <action android:name="android.intent.action.MEDIA_EJECT"/>
            <action android:name="android.intent.action.MEDIA_BAD_REMOVAL"/>

            <data android:scheme="file"/>
        </intent-filter>
    </receiver>
Run Code Online (Sandbox Code Playgroud)

挂载时为android.intent.action.MEDIA_MOUNTED,挂载的 SD 卡的根目录路径作为此操作的额外内容 - /storage/A13D-EF43。USB OTG 安装事件也是如此。唯一的区别在于安装的 USB OTG 的名称 - 路径是/storage/BD76-24ED

如果我在安装之前没有 API 调用来获取 SD 或 USB OTG 的名称,以便将其与android.intent.action.MEDIA_MOUNTED中的额外(路径)进行比较,我如何了解安装了哪种媒体 - SD 或 USB OTG ?

android usb-drive android-sdcard removable-storage android-broadcastreceiver

5
推荐指数
0
解决办法
640
查看次数

单元测试BroadcastReceiver

我一直在试图弄清楚如何对我的BroadcastReceiver进行单元测试,我已经看过StackOverflow和其他网站,但我无法找到问题的解决方案.

在我的mainActivity中,我有以下两个功能:

private void registerNetRcvr(){

    if (!isRcvrRegistered) {        
        isRcvrRegistered = true;
        registerReceiver(receiver, new IntentFilter("android.net.wifi.STATE_CHANGE"));
        registerReceiver(receiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
    }
}

private BroadcastReceiver receiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {

        NetworkHandler.NetworkInfo netInfo = NetworkHandler.handleBcastReceiver(context);

        if (netInfo!=null){
            handleInfoChange(netInfo);
        } else {
            handleInfoChange(null);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

registerNetRcvr是从onResume函数中调用的(同样我有一个从onPause调用的注销).

从上面可以看出,我有一个函数(handleBcastReceiver)被调用来处理onReceive事件,因此有另一个类,然后有一个从这个函数调用的各种私有函数.

只是稍微复杂一点......在调用onReceive函数时,如上所述,'handleBcastReceiver'函数需要'retreive'正确的数据......并且因此会调用实际检索适当的系统数据如下:

private static NetworkInfo getWiFiNetworkInfo(Context context) {

    ConnectivityManager connManager = (ConnectivityManager)
            context.getSystemService(Context.CONNECTIVITY_SERVICE);
    return connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
}
Run Code Online (Sandbox Code Playgroud)

我相信我应该模仿onReceive回调的行为,但我想模拟在调用getWiFiNetworkInfo期间从系统返回的内容.

我的想法是我应该使用RoboElectric这样做,因为它可以遮蔽BroadcastReceiver/ConnectivityManager.我也看过Mockito然而我相信RoboElectric是我需要的,但我接受我可能是错的.据我所知,RoboElectric允许我模仿'Android系统',Mockito允许我模拟我自己的课程.

目前我只是看不出如何测试BroadcastReceiver.另外,我不清楚是否应该运行模拟器来执行此操作,或者只是"运行"我的单元测试,因为"阴影"应该包含我需要的所有内容.最后,如果我要影响BroadcastReceiver,我如何通过此影子过程使WIFI"启用"或"禁用"?事实上,我应该模拟BroadcastReceiver还是只是连接管理器...我真的很困惑!

到目前为止我所做的是在我的应用程序的测试部分(而不是'androidTest'部分)中创建一个BroadcastReceiverTest类.我可以对函数进行常规的简单单元测试,我只是坚持如何模拟这个'系统'行为.

一如既往,非常感谢任何帮助.

android unit-testing mockito robolectric android-broadcastreceiver

5
推荐指数
1
解决办法
4502
查看次数

我总是在 android 7 中看到“E ActivityManager: Sending non-protected broadcast from system”。这是什么意思?

我正在尝试使用以下函数从非系统应用程序发送意图。

public static void sendIntent() {
        if (null != _context) {
            Intent intent = new Intent("com.test.testApp.testIntent");
            intent.setPackage(_context.getPackageName());
            _context.sendBroadcast(intent);
        }
    }
Run Code Online (Sandbox Code Playgroud)

但我总是看到来自 ActivityManager 的错误消息如下。相同的意图广播(应用程序)在 andorid 6.0 中工作正常,但在 android 7.1.1 中引发错误。我需要为 android 7.1.1 更改任何内容吗?

4-10 15:06:34.423 1615 2921 E ActivityManager:从系统 2886:com.test.testApp/u0a117 pkg com.test.testApp 发送不受保护的广播 com.test.testApp.testIntent

在 ListFragment 中,我按如下方式注册接收器:

 @Override
    public void onStart() {
        super.onStart();
        getActivity().registerReceiver((receiver),
                new IntentFilter(com.test.testApp.testIntent));
        TextView textDownload = (TextView) getActivity().findViewById(R.id.output);
        textDownload.setVisibility(android.view.View.INVISIBLE);
    }
Run Code Online (Sandbox Code Playgroud)

android android-intent android-broadcastreceiver android-7.1-nougat

5
推荐指数
1
解决办法
2万
查看次数

如何检测 Android O 的进程前台

在我们的应用程序中,有一个服务通常在Application.OnCreate(直接调用context.startService)期间启动,稍后通过AlarmManager(正在进行重构以将其某些工作迁移到 JobScheduler)。

我们的应用程序也有一个BroadcastReceiver以其直接意图启动的。

鉴于 Android Oreo ( https://developer.android.com/about/versions/oreo/android-8.0-changes.html ) 中的新限制,我们遇到了如下问题:

  • 应用程序/进程在后台/已死
  • BroadcastReceiver 被操作系统触发
  • Application.onCreate() 在 BroadcastReceiver 之前执行
  • Application.onCreate() 代码尝试运行服务

这会导致“IllegalStateException: Not allowed to start service Intent”崩溃。

我知道 CommonsWare 在此处/sf/answers/3115400361/所回答的启动服务的新推荐方法,但对于这种特定情况,我只想将if(process in foreground) { startService }. 我目前正在使用以下方法,它似乎有效:

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static boolean isProcessInForeground_V21(Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.AppTask> tasks = am.getAppTasks();
        return tasks.size() > 0;
    }
Run Code Online (Sandbox Code Playgroud)

但我找不到 Android Oreo 正在做的确切检查(我到这里为止https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ContextImpl.startServiceCommon方法上的java,但从那里requireForeground标志似乎转到了一些本机实现)

所以我的问题: …

android android-broadcastreceiver android-8.0-oreo

5
推荐指数
1
解决办法
753
查看次数

广播接收器在 Android 8 的前台服务中不起作用

我正在尝试创建一个应用程序,允许用户在设置的时间间隔内或手动使设备静音。我还希望用户能够输入更复杂的规则,例如仅在连接到某个 WiFi 网络、蓝牙设备或进入地理围栏时才将手机静音。但是,在静音模式下,我希望允许用户创建电话仍应响铃的联系人列表。

为此,我创建了一个前台服务,在其中注册了一个广播接收器。但是,在活动离开前台仅几分钟后,接收器就会停止按时工作并不时更新。

此问题出现在搭载 Android 8 的设备(华为/荣耀 7x)上。

注意:我尝试将应用程序添加到Doze 白名单并禁用供应商特定的电池优化,但没有任何改变。

下面是我的代码的 MCVE。每当服务中的接收器被触发时,一些 int 值就会增加,然后它们会显示在通知中。在我的设备上,由于活动离开前台,值在几分钟后停止增加:

清单权限

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
Run Code Online (Sandbox Code Playgroud)

清单声明的服务

<service android:name=".PhoneService"/>
Run Code Online (Sandbox Code Playgroud)

在 Activity 中启动 Service

//for the sake of simplicity, I omit the code where runtime permissions are requested
Intent foregroundIntent = new Intent(this, PhoneService.class);
foregroundIntent.putExtra(PhoneService.EXTRA_ACTION, PhoneService.ACTION_START);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(foregroundIntent);
} else {
    startService(foregroundIntent);
}
Run Code Online (Sandbox Code Playgroud)

服务类

public class PhoneService extends Service {

private static final String NOTIFICATION_CATEGORY = "notification_category";
private static …
Run Code Online (Sandbox Code Playgroud)

android android-service android-broadcastreceiver android-doze

5
推荐指数
1
解决办法
3349
查看次数

带 Room 的 Android BroadcastReceiver 数据库访问

我设置了一个闹钟,每小时调用一个广播接收器。此接收器尝试从 sqlite 数据库加载数据。

问题是,提醒列表为空。相同的代码适用于活动,但不适用于接收器。有什么我必须改变才能访问接收器中的数据库的吗?这是活动和接收器中不同上下文的问题吗?

“setAlarm”方法是我用来创建活动警报的方法。

问候

public class AppReceiver extends BroadcastReceiver {

    private static final String TAG = "AppReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        ReminderRepository mRepository; = new ReminderRepository(context);
        List<Reminder> list = mRepository.getAllReminder();
        for(Reminder r : list) {
            // TODO
        }
    }
}


public class ReminderRepository {

    private ReminderDao mReminderDao;
    private List<Reminder> mAllReminder;

    public DisposalCalenderRepository(Context context) {
        ReminderRoomDatabase db = ReminderRoomDatabase.getDatabase(context);
        mReminderDao = db.reminderDao();
        mAllReminder = mReminderDao.getAll();
    }

    public List<Reminder> getAllReminder(){
        return mAllReminder;
    }

}

@Dao
public …
Run Code Online (Sandbox Code Playgroud)

android broadcastreceiver android-database android-broadcastreceiver android-room

5
推荐指数
1
解决办法
2831
查看次数

服务泄露了最初在这里注册的 IntentReceiver。您是否错过了对 unregisterReceiver() 的调用?

我正在使用前台 AndroidService通过 REST API 请求一个带有 Retrofit 的资源,作为每 60 秒的计时器。此类服务也在与应用程序不同的进程中运行,这是必要的,以便 Android 在进入 Doze 模式时不会杀死它。

public class ResourceService extends Service {

   ...

   private BroadcastReceiver mReceiver;

   @Override
   public void onCreate() {
      super.onCreate();
      // create mReceiver (BroadcastReceiver)
      // create intentFilter (IntentFilter)     
      registerReceiver(mReceiver, intentFilter);
   }

   ...
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
      // main logic
   }

   @Override
   public void onDestroy() {
      super.onDestroy();
      unregisterReceiver(mReceiver);        
   }
}
Run Code Online (Sandbox Code Playgroud)

当我注销应用程序时,onDestroy()方法被调用,因此unregisterReceiver()也被调用。应用程序按预期进入登录活动,服务成功停止。但是,logcat 出现以下异常:

09-18 09:30:06.627 849-849/foo.mycompany.es.myapp:externalProcess E/ActivityThread: Service foo.mycompany.es.myapp.resources.ResourcesService has leaked …
Run Code Online (Sandbox Code Playgroud)

java android android-service android-broadcastreceiver

5
推荐指数
1
解决办法
3229
查看次数

新短信检索器 API 的广播响应延迟

最近我们决定开始使用SMS Retriever API来读取 OTP。我遵循了所有步骤并且它工作正常

问题是在长时间延迟后BroadcastReceiver得到回调。一旦实际收到短信,系统就会推送短信通知。但是,接收者将在大约一分钟后收到它。

在三星 J3 emerge 上测试。Android 6.0.1、PlayServices 14.5.81。

有人遇到过这个问题吗?API 是否存在接收者优先级问题或任何其他限制?

android android-intent android-broadcast android-broadcastreceiver android-sms

5
推荐指数
0
解决办法
500
查看次数