BroadcastReceiver with acton SCREEN_ON in background - java

I want to listen when screen of device is on and update widget but BroadcastReceiver does not work when I close my app. It works only when application is running.
AndroidManifest.xml:
<receiver
android:name=".WidgetProvider"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="android.intent.action.SCREEN_ON"/>
<action android:name="android.intent.action.SCREEN_OFF"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info"/>
</receiver>
The code is in onCreate():
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new WidgetProvider();
registerReceiver(mReceiver, intentFilter);

Since Android 8, the background processes have been restricted due to safety and battery consumption. Some Broadcast Receivers like:-
SCREEN_OFF
TIME_TICK
etc..
have been blocked.But, some of them like this:
REBOOT
work fine. This is to save the battery consumptions. This also prevents our app from opening activities when they are not necessary too.

Related

Launching an android app when phone connected to power source

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)

Run Android app in background without user interaction

I have an android app which keeps updating logs every 5 minutes.
I used Alarm Manager to achieve this.
But the app kept opening and closing automatically.
Is there any way to do this in background??
you can use android Services for this task.
http://developer.android.com/guide/components/services.html
First of all, you have to user `Service: http://developer.android.com/guide/components/services.html
Next, you can start your program in background on BOOT event:
public class BootReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, LogService.class);
context.startService(myIntent);
}
Declare theese in your manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Declaring broadcast receiver for BOOT_COMPLETED event -->
<receiver android:name=".BootReciever" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

how to start activity when android turned on?

I have the next code:
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent startActivityIntent = new Intent("android.intent.action.MAIN");
startActivityIntent.setClass(context, MainActivity.class);
startActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityIntent.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
context.startActivity(startActivityIntent);
}}
And the manifest:
<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="false" android:label="BootCompleteReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME"/>
</intent-filter>
</receiver>
It works perfectly when I turn on the device the activity starts, but I think it take about 30 seconds, I think is too much time, I want to do something like the Famigo's app, when the device is turned on inmediately start.
There is no way for you to speed up this process. It takes 30 seconds on your device, because the program has to wait until your device is completely booted. Boot_Completed is the first notification that the system sends out after boot.
Google has done this intentionally to prevent apps from starting before the system is finished booting.
the reciver calls BootCompleteReceiver, the reciver will start after the boot will complete.
it takes about 30 seconds.
you cant start the app before the OS!

Android 3.1 USB-Host - BroadcastReceiver does not receive USB_DEVICE_ATTACHED

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.

Android, Start App on Launch of Emulator

I want to do some testing on the Android emulator to run an app of mine automatically and pass it a parameter how can I do this?
For now lets assume, I have an app that opens a URL (parameter) in a browser. How can I get my emulator to do this upon launch of app?
This is for testing and this app will not be give to other to be used.
Thanks all
You want to add the "boot completed" permission, then add an intent for the broadcast and make a broadcastreceiver:
--in your manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
--and also in the manifest:
<receiver android:name=".receiver.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
--then make a receiver:
public class MyBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//use an intent to stat your activity here!
}
}

Categories

Resources