In my app when some connections happen, the user should make some decisions. I want the user to do it within a dialog. so if the screen is unlocked show the dialog instantly and if the screen is locked turn on the screen and show the notification (like SMS notifications)and when the user touches the notification and unlocks the screen see the dialog.
Take a look at the wake lock which allows you to turn the screen on and keep it on for some time you need.
Here is the example.
Create a Broadcast receiver:
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
this.registerReceiver(mReceiver, filter);
From the Reciever you will know when screen is on or off:
public class ScreenReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
screenon = false;
}
else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
{
screenon = true;
}
}
}
Don't forget to declare receiver in the manifest.
Showing notification and dialog shouldn't be the problem.
Use android docs.
Just send your notification normally and add the following flags to the activity that is called from the notification.
YourNotificationService.java
Intent intent = new Intent(context, YourActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
YourActivity.java
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
...
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
+ WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
);
...
}
Related
I followed this developer tutorial, and have Geofencing working within my app, as expected.
A notification is sent when a Geofence Transition occurs, from within an IntentService:
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
...
sendNotification(geofenceTransitionDetails);
}
private void sendNotification(String notificationDetails) {
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Define the notification settings.
builder.setSmallIcon(R.mipmap.ic_launcher)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setColor(Color.RED)
.setContentTitle(notificationDetails)
.setContentText("Return to app")
.setContentIntent(notificationPendingIntent);
// Dismiss notification once the user touches it.
builder.setAutoCancel(true);
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
This is cookie-cutter from the tutorial. The intent is set-up in the Main activity:
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
// addGeofences() and removeGeofences().
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
How can I add functionality that suppresses the notifications if the app is open, and instead displays an AlertDialog to the user? Ideally, I'd like to be able to execute different tasks, depending on which view the user is currently in when the Geofence Transition occurs. Can I monitor/intercept the transition from within each view, or somehow globally?
Thanks in advance.
Some of the answers were incomplete, and so here is the complete solution to what I was looking for.
First off, set up MyApplication class, that implements ActivityLifecycleCallbacks:
public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {
private static boolean isActive;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
public static boolean isActivityVisible(){
return isActive;
}
#Override
public void onActivityResumed(Activity activity) {
isActive = true;
}
#Override
public void onActivityPaused(Activity activity) {
isActive = false;
}
... no other methods need to be used, but there are more that
... must be included for the ActivityLifecycleCallbacks
}
Be sure to name this in your manifest (only name line was added, rest is default):
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:hardwareAccelerated="true">
What was done above is used to track the lifecycle of your app. You can use this to check if your app is currently in the foreground or not.
Next is to set up a BroadcastReceiver, wherever you would like code to run (in the event that the app is open when the trigger occurs). In this case, it is in my MainActivity:
protected BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
... Do whatever you want here
Toast.makeText(...).show();
}
};
Register the receiver in your onCreate of the same activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
LocalBroadcastManager.getInstance(this).registerReceiver(mNotificationReceiver, new IntentFilter("some_custom_id"));
}
And don't forget to unregister it:
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mNotificationReceiver);
super.onDestroy();
}
When a broadcast is received, the code within the receiver is executed.
Now, to check if the app is in the foreground, and send a broadcast if it is. Inside of the IntentService:
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = getErrorString(this,
geofencingEvent.getErrorCode());
return;
}
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
...
if(MyApplication.isActivityVisible()){
Intent intnt = new Intent("some_custom_id");
intnt.putExtra("message", geofenceTransitionDetails);
LocalBroadcastManager.getInstance(this).sendBroadcast(intnt);
}else{
sendNotification(geofenceTransitionDetails);
}
} else {
// Log the error.
}
}
The important bit is the last nested if-statement:
if(MyApplication.isActivityVisible()){
Intent intnt = new Intent("some_custom_id");
intnt.putExtra("message", geofenceTransitionDetails);
LocalBroadcastManager.getInstance(this).sendBroadcast(intnt);
}else{
sendNotification(geofenceTransitionDetails);
}
Check if the app is in the foreground using MyApplication.isActivityVisible(), as defined above, and then either send the notification, or send a broadcast. Just make sure that your intent code (i.e. "some_custom_id") matches on your sender and receiver.
And that's about it. If the app is in the foreground (specifically the MainActivity), I execute some code. If the app is not in the foreground, I send a notification.
The easiest way would be to use LocalBroadcastManager or some event bus.
So when transition happens you should send local broadcast from IntentService and catch it with some component X in between IntentService and any of your Activity's. Component X must track if any of your Activity's is in foreground and
if yes - pass other local broadcast up (to the foreground Activity),
if not - show notification.
Please note that in Android you cannot track easily if your app is in foreground or not (and if you have more than 1 Activity, you cannot do it properly in my opinion) but you can try.
a) You can notify your service of the activity's lifecycle events.
b) You can keep the current state of your UI in a static field in the activity and check it from the service before showing the notification.
I have broadcastreceiver in my application and it's work good, when i connect with the smart phone to bluetooth device it's show me a alert dialog.
But, if the screen is off or in the lock screen, it's not show me the alert dialog, and i want to show the alert dialog even if the smartphone on the lock screen or the screen off.
How i can do this?
Thanks!
public class ScreenReceiver extends BroadcastReceiver {
public static boolean wasScreenOn = true;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
//do something here
}
}
}
This is how you register the receiver.
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
Since you didn't provide any code, I cannot be sure about this. However, your problem might be related to the context from which you are declaring the Intent (if any), or anyway the dialog. Try to use context.getApplicationContext() instead of context / this:
final Intent dialogIntent = new Intent(context.getApplicationContext(), DialogActivity.class);
context.startActivity(dialogIntent);
Screen Off ,Broadcast Receiver does not call some time it will execute but mostly wifi state change event is called .i have also set up the priority of screen off but does not call or some time call .can you please tell .when my screen off i want to execute first then other wifi state changed will called
BroadcastReceiver wReceiver = new ScreenReciver();
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.setPriority(1);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.setPriority(1000);
registerReceiver(wReceiver, filter);
}
#Override
protected void onPause() {
unregisterReceiver(wReceiver);
super.onPause();
}
public class ScreenReciver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
switch (wifiState) {
case WifiManager.WIFI_STATE_DISABLED:
Intent myintent = new Intent(context, TimerClockActivity.class);
myintent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
myintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myintent);
wifiStateText = "WIFI_STATE_DISABLED";
break;
default:
break;
}
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Intent myintent = new Intent(context, TimerClockActivity.class);
myintent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
myintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myintent);
}
}
}
You are calling unregisterReceiver(wReceiver); in onPause(). This means that every time that the Activity goes into the background (including when the screen turns off), your Activity is unregistered for that broadcast.
onPause() is likely getting called before your Activity gets a chance to receive the Broadcast.
Perhaps you want to place unregisterReceiver(wReceiver); in onDestroy() instead?
I've a Broadcast receiver:
public class ScreenReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
//Do something
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Intent start=new Intent(context,MainActivity.class);
context.startActivity(start);
}
}
}
And, in my activity, into onCreate():
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
ScreenReceiver mReceiver=new ScreenReceiver();
registerReceiver(mReceiver, filter);
The problem is that, when my activity is displayed, the receiver performs correctly the action, but when it is in background, sometimes nothing happens.
What could be the issue?
Most likely, when your app goes into the background Android kills it to free up resources. Try starting a foreground service attached to an ongoing notification from your Activity, and register the BroadcastReceiver in that.
I'm trying to make a custom lock screen app, but I'm not sure if I'm going about it the right way. I have a broadcast receiver that listens to when the screen is turned on and starts my lock screen activity. This receiver is registered inside a service, which also disables the default lock screen.
The problem is, there is a slight delay between when the screen is turned on and the lock screen activity shows up. How would I go about doing it so that it shows up right away?
My code for the service:
#Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver powerReceiver = new PowerReceiver();
registerReceiver(powerReceiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Service.KEYGUARD_SERVICE);
KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.disableKeyguard();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
and the receiver:
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Intent showScreen = new Intent(context, LockScreen.class);
showScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(showScreen);
}
}
Turn your app into a home screen replacement app and when the user successfully unlocks the custom lock screen you can take them to the default home app.
You can find more info in this question and these questions.