I found that in the manifest can not be registered (intent-filter battery low, battery changed).
I need to get the notification when the battery is fully charged. when I have a running app so it is working, but when I close the application so it does not work.
I need the receiver to run in the background when the application is closed.
Main.class
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
mContext.registerReceiver(this.batteryInfoReceiver,filter);
private BroadcastReceiver batteryInfoReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
...
}
Related
I'm using an Android foreground Service to download files and I'm showing the progress of the download to the user in a Notification.
I also have a progress bar in a fragment in the app.
I'm using a broadcast Receiver to communicate the progress of the download happenning in the service to my fragment.
My problem is that the onReceive of my BroadcastReceiver is not trigger above Android 11 bu works perfectly fine on android 10, What had change about broadcast reveiver since Android 11 ?
On my fragment i'm declaring my broadcast receiver :
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if ("SHOW_PROGRESS".equals(intent.getAction())) {
showProgress(intent.getIntExtra("progress", 0));
}
}
};
And registering it in OnCreateView :
IntentFilter filter = new IntentFilter();
filter.addAction("SHOW_PROGRESS");
getContext().registerReceiver(receiver, filter);
From my service I'm calling it :
Intent broadcastIntent = new Intent().setAction("SHOW_PROGRESS").putExtra("progress", downLoadState.getGlobalPercent());
getApplicationContext().sendBroadcast(broadcastIntent);
I have nothing in my manifest since my service don't interacts with device components
I'm trying to start MainActivity with BluetoothDevice.ACTION_ACL_CONNECTED receive just like in some stack overflow answers
public class BTReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("BT", "Receive");
String action = intent.getAction();
...
switch (action) {
case BluetoothDevice.ACTION_ACL_CONNECTED:
Intent i = new Intent();
i.setClassName("com.opendashcam", "com.opendashcam.MainActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
And like this
Intent intent1 = new Intent(context, MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
But all that I can see it's just these logs (first two say that receive was gotten and activity was started with connection to written MAC)
D/BT: Receive
D/BT: started app with 00:14:41:1E:26:27
I/Timeline: Timeline: Activity_launch_request time:129879532
My Main Activity's onCreate:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("MA", "Started app");
init();
}
Since Android 10, according to Android Developers docs ,Android does not allow launching an activity from the background:
Android 10 (API level 29) and higher place restrictions on when apps can start activities when the app is running in the background. These restrictions help minimize interruptions for the user and keep the user more in control of what's shown on their screen.
As an alternative, you can show notification that will launch the activity if clicked:
In nearly all cases, apps that are in the background should display time-sensitive notifications to provide urgent information to the user instead of directly starting an activity.
Not sure how to get the receiver to work on the activity once the app is forced closed.
What am I missing to get this to work even if the app was forced closed? Any help would be appreciated.
I am getting the BroadcastReceiver service to work, Just not getting anything to pick up on the activity level.
I have my receiver (Service):
public class MyReceiver extends BroadcastReceiver {
public static final String SEND_NOTIFICATION_ACTION = "com.clover.sdk.app.intent.action.APP_NOTIFICATION";
#Override
public void onReceive(Context context, Intent intent) {
Log.i("MyReceiver", "Triggered MyReceiver");
String action = intent.getAction();
Bundle getIntent = intent.getExtras();
if (action.equals(SEND_NOTIFICATION_ACTION)) {
Log.i("MyReceiver Gotten", "Found");
intent = new Intent("broadCastName");
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("orderId", getIntent.getString("payload"));
Log.i("Receiver OrderID", getIntent.getString("payload"));
context.sendBroadcast(intent);
}
}
}
My Activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(broadcastReceiver, new IntentFilter("broadCastName"));
}
}
Then my broadcastReceiver in my activity:
// Add this inside your class
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("MyReceiver Gotten 2", "Found");
Bundle b = intent.getExtras();
Log.i("MyReceiver Gotten 3", b.getString("orderId"));
new SpecificOrderAsyncTask(MainActivity.this).execute(b.getString("orderId"));
}
};
Not sure how to get the receiver to work on the activity once the app is forced closed. What am I missing to get this to work even if the app was forced closed?
That's contradictory - you can't get a receiver to work in an Activity that registered it at runtime if that Activity that is hosting the receiver is killed. When you force close, every in the app process - including the Activity and the receiver you registered with it - disappears.
The point of calling registerReceiver is to listen for broadcasts only during a specific time frame or lifecycle.
If you want the receiver to work even when the app is closed, don't register it at runtime - register it in the manifest.
Simple,
Registering service in an activity is temporary, registering service in a manifest will run even after closing the application.
But the broadcast you use is a simple message transfer system, that won't work even after you register in manifest and close the application. You have to create a background service that runs always in background in android system and should awake listening to some events passed.
For the many threads, blogs, examples and tutorials on the topic of Broadcast Receivers and mobile data connectivity i have not seen this question asked or answered.
I believe, based on experimenting with one of my Apps, that the answer to this question is a distinct NO, that while WiFi is enabled, a Broadcast Receiver listening for Mobile Data CONNECTIVITY_CHANGE does not receive a broadcast notification when that event occurs. If i am wrong and have missed something please let me know.
My App is a home screen Widget with two classes, ActiveMobileData is the AppWidgetProvider and ConnectivityChangeReceiver is the BroadcastReceiver. The AppWidgetProvider class is my first App which i put together earlier this year mainly from code widely available in a book, on StackOverflow and on various blogs etc. There is no App just the home screen widget. It simply toggles a home screen icon between red and green to indicate the current mobile data state. It has worked perfectly for several months with about 100 users.
I decided to add the BroadcastReceiver to pick up clicks from Settings. This code is also straight forward - it determines the current state of mobile data, and uses a global boolean variable set by AppWidgetProvider to determine if the home screen icon is red or green. Then it simply ensures that the icon color matches the mobile data state.
It all works except when WiFi is enabled it does not get a notification. If there is a way around this limitation i would appreciate hearing about it.
Following is the code for the widget and then for the receiver. I left out some details to keep it somewhat brief. iconEnabled is the shared global boolean variable ...
public class ActiveMobileData extends AppWidgetProvider {
static boolean iconEnabled;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null)
super.onReceive(context, intent);
else {
context.startService(new Intent(context, ToggleService.class));
}
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[]appWidgetIds) {
context.startService(new Intent(context, ToggleService.class));
}
public static class ToggleService extends IntentService {
public ToggleService() {
super("ActiveMobileData$ToggleService");
}
#Override
protected void onHandleIntent(Intent intent) {
ComponentName cn = new ComponentName(this, ActiveMobileData.class);
AppWidgetManager mgr = AppWidgetManager.getInstance(this);
mgr.updateAppWidget(cn, buildUpdate(this));
}
private RemoteViews buildUpdate(Context context) {
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget);
if (!isMobileDataEnabled(getApplicationContext())) {
updateViews.setImageViewResource(R.id.mobileDataState, R.mipmap.ic_launcher_g);
enableMobileData(getApplicationContext(), true);
iconEnabled = true;
} else {
updateViews.setImageViewResource(R.id.mobileDataState, R.mipmap.ic_launcher_r);
enableMobileData(getApplicationContext(), false);
iconEnabled = false;
}
Intent i = new Intent(this, ActiveMobileData.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
updateViews.setOnClickPendingIntent(R.id.mobileDataState, pi);
return updateViews;
}
public boolean isMobileDataEnabled(Context context) {
// ... the code here is the one that uses Java reflection
}
private void enableMobileData(Context context, boolean enabled) {
// ... the code here is the one that uses Java reflection
}
} // public static class ToggleService
} // public class ActiveMobileData
Following is the code for the BroadcastReceiver ...
public class ConnectivityChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive (Context context, Intent intent) {
handleIntent(context);
}
protected void handleIntent(Context context) {
ComponentName cn = new ComponentName(context, ActiveMobileData.class);
AppWidgetManager mgr = AppWidgetManager.getInstance(context);
mgr.updateAppWidget(cn, buildUpdate(context));
}
private RemoteViews buildUpdate(Context context) {
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget);
if (!ActiveMobileData.iconEnabled && isMobileDataEnabled(context)) {
ActiveMobileData.iconEnabled = true;
updateViews.setImageViewResource(R.id.mobileDataState, R.mipmap.ic_launcher_g);
Intent i = new Intent(context, ActiveMobileData.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
updateViews.setOnClickPendingIntent(R.id.mobileDataState, pi);
} else
if (ActiveMobileData.iconEnabled && !isMobileDataEnabled(context)) {
ActiveMobileData.iconEnabled = false;
updateViews.setImageViewResource(R.id.mobileDataState, R.mipmap.ic_launcher_r);
Intent i = new Intent(context, ActiveMobileData.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
updateViews.setOnClickPendingIntent(R.id.mobileDataState, pi);
}
return updateViews;
}
private boolean isMobileDataEnabled(Context context) {
// ... Identical code to that in the AppWidgetProvider
}
} // class ConnectivityChangeReceiver
I don't know offhand, but I can point you to the 2 best places to look.
Best bet would be to look in detail into the JavaDoc for ConnectivityManager.html#CONNECTIVITY_ACTION and then the source code for the ConnectivityManager that is online on GrepCode
In particular comments within the source code often have very informative information that doesn't exist elsewhere.
Update:
After reading the javadoc for CONNECTIVITY_ACTION again, I believe that you are correct because it say A change in network connectivity has occurred. A default connection has either been established or lost. NOTE: Default Conn. NOT 'A Conn.' So it only gets launched when the 'default' changes. So if you lose 3g/4g/etc while on WIFI then I don't think this gets launched.
However there 'is' something you 'can' do... (but only when your widget is running) (I'm actually not 100% sure a 'widget' CAN do this... b/c I generally work with teaching services/AIDL/ContentProviders/etc (aka. 'backend' stuff within the platform) But you can put a 'refresh' button on your widget that can query to GET ALL NETWORKS and then parse through all that data and display which networks 'are' active, etc.
Also there is the option. You could make pending intents for your broadcast receiver(s) (I'd recommend just 1 BR and have different payloads so you can sort them for what is being notified) then register each of those pending intents as a call back with the ConnectivityManager to notify it whenever a 'network' that 'matches' the NetworkRequest exists. This will notify you at least when they 'come alive'...
(this next idea would likely require you to make a service with a separate thread to prevent ANR)
now when they 'die'... you 'could' setup a TCP connection and see when it dies... (not 'good' but might be only 'viable' option) (and if you are are 'generous' with trying to not wake up the phone, the battery impact could be minimal)
In my application, I am starting the VIBRATOR_SERVICE through the following code
long[] pattern = {50,100,1000}
Vibrator vibe=(Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibe.vibrate(pattern, 0);
I want the vibration continue till I call
vibe.cancel();
The Code is working fine, but the vibration getting off when the screen goes to sleep mode.
I want the vibration continue even after the screen goes to sleep mode. Is there any ways to do this? Please help me.
Thanks in advance. :)
The correct answer to the question is as follows
Before doing this, don't forget to add the permission "android.permission.VIBRATE" to your app manifest file.
public BroadcastReceiver vibrateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
vibe.vibrate(pattern, 0);
}
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(vibrateReceiver, filter);
wakelock will not work here, because the receiver will receive the intent only after the screen goes off. Though we can acquire the wakelock after the screen goes to off mode the vibration stops, because it happens with the ACTION_SCREEN_OFF. So it can be done by starting the vibration again after receiving the broadcast.
Try this it might help you. First make broadcast receiver for this such that when mobile light screen off then write logic of vibrate mobile.
public BroadcastReceiver wakeLockReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
//WRITE LOGIC OF VIBRATION.
}
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(wakeLockReceiver, filter);
Add permission in AndroidManifest.xml
<uses-permission android:name="android.permission.VIBRATE"/>