I have created Accessibility service in Android and it works perfectly on 4.2 (Jelly Bean) and 5.1 (Lollipop) but not on 4.4 (KitKat).
On KitKat, it doesn't receive ANY events and doesn't call onAccessibilityEvent at all.
Am I doing something wrong?
Here's my implementation:
accessibilityservice.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeNotificationStateChanged"
android:accessibilityFeedbackType="feedbackAllMask"
android:canRetrieveWindowContent="true"
android:description="#string/app_name"
android:notificationTimeout="100" />
myAccessibilityService.java
public class myAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent e) {
if (e.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
Log.d(TAG, "NOTIFICATION!!");
}
}
#Override
protected void onServiceConnected() {
Log.d(TAG, AccessibilityService Connected");
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
info.flags = AccessibilityServiceInfo.DEFAULT;
info.notificationTimeout = 100;
setServiceInfo(info);
}
#Override
public void onInterrupt() {
Log.d(TAG, "myAccessibilityService onInterrupt Called");
}
}
AndroidManifest.xml
<service
android:name=".myAccessibilityService"
android:enabled="true"
android:label="#string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/accessibilityservice" />
</service>
When I go to settings and turn the service on, onServiceConnected is called and it says it's on and running BUT it never called onAccessibilityEvent.
Like I said, it works on JellyBean AND Lollipop. So what could be the problem?
When you create a new service info, you remove a lot of the default properties of the service info. I recommend fetching the service info of the service, and then manipulating that object. I'm not convinced this will fix your problem, but it's a better idea in general.
To clarify, I recommend exchanging this line:
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
With this:
AccessibilityServiceInfo info = this.getServiceInfo();
So that you maintain the default configuration from any XML properties, default construction, etc.
First of all, in onServiceConnected(), remove all the lines except the Log.
Your Accessibility service can miss events if you have any other accessibility service with same package name & registered for same events installed on the device.
Also,
1) Try to check other events like TYPE_WINDOW_CONTENT_CHANGED and see if KitKat device receives them.
2) Try running on a different version of KitKat (might be a version issue).
Related
I am new to flutter, I am trying to create a service in the background when starting Android occupying the main java class since in flutter it cannot be done, so I want to start a service in its background from here
package com.example.flutter_app_services;
import android.os.Bundle;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
I have seen many queries with the following code:
Java class
import android.app.Service;
import android.content.*;
import android.os.*;
import android.widget.Toast;
public class ServiceBack extends Service {
public Context context = this;
public Handler handler = null;
public static Runnable runnable = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Start", Toast.LENGTH_LONG).show();
handler = new Handler();
runnable = new Runnable() {
public void run() {
Toast.makeText(context, "In Run....", Toast.LENGTH_LONG).show();
handler.postDelayed(runnable, 10000);
}
};
handler.postDelayed(runnable, 15000);
}
#Override
public void onDestroy() {
Toast.makeText(this, "Stop", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "initialized", Toast.LENGTH_LONG).show();
}
}
Start Service
startService(new Intent(this,ServiceBack.class));
This is my AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.flutter_app_services">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:label="flutter_app_services"
android:icon="#mipmap/ic_launcher">
<service android:enabled="true" android:name=".ServiceBack" />
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="#drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
The main problem is that I don't know how to implement it in the "Flutter Activity".
I am trying to make a service that starts in BOOT and when I close the main application the service continues in the background (it is important that it does not stop), but none of this works either, I need help, I have looked everywhere and nothing. I use the Android 11 operating system.
You won't get what you want. In Android, there are 2 types of services- Foreground and Background.
Background services can be killed at any time. They will be killed by the OS a few minutes after starting. They're meant for short duration tasks in the background that need a valid Android Context object.
Foreground services can be killed at any time. They show a notification to the user that the service is running, so the user knows what's going on at all times. Foreground services are lower on the kill list than background services so they won't be killed immediately, but the OS can and will kill them for resources whenever it thinks it needs them. They are not reliable.
There is no reliable way to run a background service like you would on a PC. Instead, you need to architect your code to work on an event driven basis so that it can respond to OS or time events and do work as needed, rather than waiting around for a request to be made.
More focused advice on how to do that would require a lot more details about what you're trying to do.
I am trying to write an android app that should be launched, whenever the phone with the app is plugged to the AC power or connected through usb cord to, say a laptop. The behavior i want is that even when the android app is closed, once i plugged the phone to the power source, the app should launch and come to view.
i added the following to the AndroidManifest.xml file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.chargeit">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<receiver android:name=".OnPowerReceiver">
<intent-filter>
<action
android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I also added this to MainActivity
class OnPowerReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
val i = Intent(context, MainActivity::class.java)
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(i)
}
}
However, when i ran and connect the device to power, the android app did not launch(come up). I would have preferred to code this solution using flutter but i learnt that flutter might not be a strong candidate for that level of interaction with phone hardware.
Please what am i doing wrong? Any help will be greatly appreciated. Thanks
I think android.intent.action.ACTION_POWER_CONNECTED is not exempted from background broadcast list
you must explicitly register for it from your Java code to make it work.
and as part of the Android 8.0 (API level 26) Background Execution Limits, apps that target the API level 26 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest. However, several broadcasts are currently exempted from these limitations. Apps can continue to register listeners for the following broadcasts, no matter what API level the apps target.
Please refer to below documentation for your broadcast too -
broadcast
You can register like below -
private BroadcastReceiver receiver;
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.ACTION_POWER_CONNECTED");
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
};
registerReceiver(receiver, filter);
}
And to unregister -
#Override
protected void onDestroy() {
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
super.onDestroy();
}
In my project, I can't receive any event when I only set intentFilter.
But If I set a high priority to intentFilter, I receive the power connected or disconnected event every time(I test with an android 11 device):
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_POWER_CONNECTED)
intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED)
intentFilter.priority = IntentFilter.SYSTEM_HIGH_PRIORITY
registerReceiver(PowerConnectionReceiver(), intentFilter)
So I've built a small Google Glass application using the GDK which basically fakes a push notification by opening a Thread in the background and polling a RESTful webservice every few seconds.
Currently when I open the application it loads and runs the service but the onStart() and onCreate() for the activity (where the Thread is) doesn't get called until the user interacts with the app by opening the menu.
I've never done Android development before so I don't know why my activity might not be loading as soon as the user starts the app.
Here's an overview of some of the code.
public class MainActivity extends Activity {
#Override
protected void onStart()
{
super.onStart();
startThread();
}
Then the actual thread (I know it's terrible it's a prototype :-P)
public void startThread()
{
thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(5000);
boolean tmp = poll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
And the Android Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testpack"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
<application
android:allowBackup="true"
android:icon="#drawable/logo_box"
android:label="Test">
<uses-library
android:name="com.google.android.glass"
android:required="true" />
<activity
android:name="com.testpack.MainActivity"
android:theme="#style/MenuTheme"
android:enabled="true"/>
<service
android:name="com.testpack.MainService"
android:label="#string/app_name"
android:icon="#drawable/logo_box"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/hello_show" />
</service>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Unlike most regular android apps, Glassware typically launches a Service (which runs in the background) rather then an activity (which is a foreground task). Is is because a lot of the time you will want to interact with the timeline (i.e. add live cards etc) rather than take over the whole screen with an activity (or an immersion in Glass speak).
In your manifest you are launching MainService with a voice command, but your code is in MainActivity.
If you put your code to start the thread in the onStartCommand method of MainService that should start as soon as the app is launched from the menu/voice command.
I hope that makes things clearer.
First I wan't to say that I tried to find my answers on stackoverflow with no success. Second, I tested my code on my Samsung S3 4G 4.1.2.
I have some question with the code I produced.
---Exlaination :
The code starts ClsAutoStart at BOOT_COMPLETED, which starts a service, SvcFirst, which register a BroadcastReceiver synchronized with NEW_OUTGOING_CALL action. In the onReceive() method, I start the activity.
You understood that the activity is supposed to popup when the is a call (no condition yet).
---Questions :
This works but I DO NOT have the exact expected behaviour so I have some questions :
1- Everything goes well ONLY if I first open the activity AFTER installation and BEFORE reboot. Then, after that, every piece of code does what it has to. Could anyone explain me why I have to launch the activity in order it to work ? How to avoid it ?
2- The reason why I use this method to do things is because I don't want my application to appear in the application list (for the user). I wan't the activity to be launched by the onReceive method.
I tried to remove the following lines from the manifest file but I go back to question "1" : if I can't previously launch the activity, it doesn't work (no possibility to launch anything because the lines are removed).
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Could anyone explain me why I doesn't work and how to correct it ?
Is this the correct way to do "hide" my application ?
On stackoverflow, I found many answers ... this is one of them (question "3" is one of the others ...).
3- I removed the previous lines (question "2) and add the following one in the receiver section (of BOOT_COMPLETED action) in my manifest file but it still doesn't change anything. Any clue ?
<category android:name="android.intent.category.HOME" />
---Code :
manifest file :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.frontal.invisible04"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.frontal.invisible04.ActMain"
android:label="#string/title_activity_act_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.frontal.invisible04.SvcFirst">
</service>
<receiver
android:name="com.frontal.invisible04.ClsAutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<!--<category android:name="android.intent.category.HOME" />-->
</intent-filter>
</receiver>
</application>
</manifest>
ClsAutoStart :
public class ClsAutoStart extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if ((intent.getAction() != null) && (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")))
{
context.startService(new Intent(context, SvcFirst.class));
}
}
}
SvcFirst :
public class SvcFirst extends Service
{
Context context;
private BroadcastReceiver br_interface;
private static final String ACTION_SHOWACT = "android.intent.action.NEW_OUTGOING_CALL";
#Override
public void onCreate()
{
super.onCreate();
this.context = getApplicationContext();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SHOWACT);
this.br_interface = new SecretInterfaceBR();
this.registerReceiver(this.br_interface, filter);
return (START_STICKY);
}
public class SecretInterfaceBR extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Intent intent1 = new Intent(context, ActMain.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
context.startActivity(intent1);
}
}
#Override
public IBinder onBind(Intent intent)
{
return (null);
}
public void onDestroy()
{
this.unregisterReceiver(this.br_interface);
}
}
Thanks for your help.
Could anyone explain me why I have to launch the activity in order it to work ?
Because manifest-registered receivers will not work while the app is in a force-stopped state, as of Android 3.1. That occurs:
On first install
After the user taps the "Force Stop" button in Settings
How to avoid it ?
Only support Android 3.0 and below. Note that this is a diminishing percentage of the Android device market.
Could anyone explain me why I doesn't work and how to correct it ?
See above.
Is this the correct way to do "hide" my application ?
What you are describing does not hide an application, but merely represents an application with no launcher icon. Such applications typically are not useful as of Android 3.1, due to the aforementioned force-stopped restriction. And, these applications are still listed everywhere else that chooses to list applications, such as the Settings app.
I removed the previous lines (question "2) and add the following one in the receiver section (of BOOT_COMPLETED action) in my manifest file but it still doesn't change anything. Any clue ?
A <category> is rarely used with a receiver. The HOME category is used with activities and designates a home screen implementation.
I worked through the description and samples for USB host at developer.android.com to detect attached and detached USB-devices.
If I use an intent-filter in the manifest file to start my application when a device is attached, it works perfectly fine: Plug in, device is detected, android asks for permission to start the application, device information is displayed in a table.
The application I'm developing shouldn't be started/finished only if a device is attached/detached (e.g. data management purposes). Also I do not want the open-dialog to pop up if the app is already running. So I decided not to start the activity directly if a device is attached, but to register a BroadcastReceiver, which is (later) supposed to notify the activity if a device is at-/detached. This receiver recognizes the detach-action just fine, but not the attach-action.
Am I missing a permission or data attribute or something like that? The tutorial and samples don't say anything about additional necessary attributes.
Here is the manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="de.visira.smartfdr"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12" />
<uses-feature android:name="android.hardware.usb.host" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".usb.Detector">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
android:resource="#xml/device_filter" />
</receiver>
</application>
And the receiver:
public class FDRDetector extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Toast.makeText(context, "Action: " + action, 3).show();
// pops up only if action == DETACHED
}
I don't understand why the same intent-filter works, if I use them on an activity, but not if they are applied to a receiver? Even if I set up the receiver and filter in code, attaches are not recognized.
My work environment:
IDE: Eclipse 3.7 with Android Plugin
Device: Acer Iconia Tab A500
Android: 3.1
Thanks in advance
Aha! I figured it out. I was having the exact same problem.
The gist of it is - if you have your application launch automatically when a device is plugged in (using the manifest file), then it appears the Android system gets the ACTION_USB_DEVICE_ATTACHED intent, and then since it knows your application wants to run in that situation, it actually sends your application the android.intent.action.MAIN intent. It never sends the ACTION_USB_DEVICE_ATTACHED action to your application because it thinks it already knows what your application wants to do in that situation.
I've just now identified the problem, and I think I have a solution, but I can tell you what I've found:
Even if your app is running and in the foreground, when you plug in the USB device and the Android system gets the ACTION_USB_DEVICE_ATTACHED intent, it will call onResume() in your activity.
Unfortunately, you cannot just do this:
#Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
Log.d(TAG, "intent: " + intent);
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
//do something
}
}
Because the intent will come back as android.intent.action.MAIN, NOT ACTION_USB_DEVICE_ATTACHED.
An annoyingly, you also get android.intent.action.MAIN if you just leave the app, but don't unplug USB. I imagine putting the device to sleep and waking it back up will do the same thing.
So from what I have found, you can't get the intent directly, but it does appear that you can rely on onResume() being called when a USB device is plugged in, so the solution is to just check to see if USB is connected every time you get an onResume. You can also set a flag when USB is disconnected, because of course the USB disconnect intent fires just fine.
So in total, your broadcast receiver might look like this:
// BroadcastReceiver when remove the device USB plug from a USB port
BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
usbConnected=false;
}
}
};
You'd have this inside of onCreate:
// listen for new devices
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(mUsbReceiver, filter);
This goes inside of the activity tag in your manifest:
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
You'll have a device_filter.xml file in your /res/xml/ folder that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1027" product-id="24577" />
<usb-device vendor-id="1118" product-id="688" />
</resources>
(of course with whatever vendor IDs and product IDs you need)
And then your onCreate looks something like this:
#Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
Log.d(TAG, "intent: " + intent);
String action = intent.getAction();
if (usbConnected==false ) {
//check to see if USB is now connected
}
}
I don't have specific code for checking to see if USB is connected as I actually haven't delved into that yet. I'm using a library that will just connect if it can, so for my application I can just start that loop and I'm good.
Its also probably important to set the launchmode of your activity in the manifest to "singleTask" to prevent it from running again when its already running, or else plugging in a USB device will just launch a second instance of your application!
So my whole activity tag in my manifest looks like this:
<activity
android:label="#string/app_name"
android:name="com.awitness.common.TorqueTablet"
android:theme="#android:style/Theme.Holo.NoActionBar.Fullscreen"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTask"
>
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
</activity>
Anyway, I hope this helps someone! I was surprised that I was unable to find a solution for this already!
Just to follow on from #Gusdor's insightful comment (+1): I implemented a check in onNewIntent() that, as #Gusdor points out, is called when your activity launchMode is set as singleTask or singleTop. Then, rather than checking for boolean flags as the accepted answer suggests, simply pass on the intent to your USB broadcast receiver using a LocalBroadcastManager. For example,
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(intent.getAction())) {
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Then, wherever you're registering your existing (system) USB broadcast receiver, just register the same receiver with a local broadcast manager instance, i.e.,
#Override
protected void onResume() {
super.onResume();
myContext.registerReceiver(myUsbBroadcastReceiver, myIntent); // system receiver
LocalBroadcastManager.getInstance(myContext).registerReceiver(myUsbBroadcastReceiver, intent); // local receiver
}
#Override
protected void onPause() {
super.onResume();
myContext.unregisterReceiver(myUsbBroadcastReceiver); // system receiver
LocalBroadcastManager.getInstance(myContext).unregisterReceiver(myUsbBroadcastReceiver); // local receiver
}
You could send another system broadcast rather than a local broadcast, but I don't think you'll be able to use the action UsbManager.ACTION_USB_ACCESSORY_ATTACHED (system would see that as potential security risk), so you'd have to define your own action. No big deal, but why bother, especially as there's no IPC overhead with local broadcasts.
Creating the broadcast receiver within the application, and not the manifest, allows your application to only handle detached events while it is running. This way, detached events are only sent to the application that is currently running and not broadcast to all applications.