How to make a screen wake up when a notification is received? - java

For my app I'm trying to get it where the notification wakes up the screen and displays a view from the app. I can't figure how to get the app to wake up when its in a lock screen. I've tried a few things but none seem to work or they crash the app.

There is my solution:
createNotification(); //your implementation
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = Build.VERSION.SDK_INT >= 20 ? pm.isInteractive() : pm.isScreenOn(); // check if screen is on
if (!isScreenOn) {
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "myApp:notificationLock");
wl.acquire(3000); //set your time in milliseconds
}
More at PowerManager

This BroadCastReceiver Works For, your App Is in back ground State/ mobile In lock mode. That time when notification is recieved i have to redirect particular screen, for that one i added Intent code,
After receiving Notification this code helps to your requirement
public class FirebaseDataReceiver extends WakefulBroadcastReceiver {
private final String TAG = "FirebaseDataReceiver";
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
if(isScreenOn==false)
{
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |PowerManager.ACQUIRE_CAUSES_WAKEUP |PowerManager.ON_AFTER_RELEASE,"MyLock");
wl.acquire(10000);
PowerManager.WakeLock wl_cpu = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyCpuLock");
wl_cpu.acquire(10000);
}
//Redirect particular screen after receiving notification, this is like ola driver app concept accepting driver request
intent = new Intent(context, MyTicketListActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
Also remember to specify the permission used in the AndroidManifest.xml:
<uses-permission android:name="android.permission.WAKE_LOCK" />

I faced a similar situation. It was required to show a notification screen for the user to accept or reject the notification, even when the screen is off. I fumbled with it for a while until now. The requirements demand the screen should be on and this can be achieved with a combination of flags for the window manager and the wake lock as shown below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
int flags = PowerManager.FULL_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE;
if (!isScreenOn) {
wakeLock = pm.newWakeLock(flags, "my_app:full_lock");
wakeLock.acquire(20000);
}
setContentView(R.layout.activity_incoming_request);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
...
startRingingPhone();
}
This code block will display the activity on the lock screen.

Put below code before notification creates,
PowerManager powerManager = (PowerManager) context.getSystemService(context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, "appname::WakeLock");
//acquire will turn on the display
wakeLock.acquire(1*60*1000L);
And make sure to set this permission in the manifest :
<uses-permission android:name="android.permission.WAKE_LOCK"/>

Related

How to open activity (incoming voip call) in Android 10

In Android 10 there apply new restrictions for apps.
We can no longer start an activity from background. While this may be fine for the majority of apps, it's a killing blow for voip-apps that need to show an incoming call after a push notification arrived.
According to this https://developer.android.com/guide/components/activities/background-starts there is a list of conditions that can be met to still allow opening an activity, but tbh I do not understand that fully (non-english-native here).
What I definitely know, is:
I do not have any running activity, task, backstack and the like
The app is NOT EVEN RUNNING
What I need to achieve:
The FCM service of the app receives a push from our server and shall present the incoming call screen (over lock screen and all - just as it did with android 9 and below)
What can I do to open an activity for an incoming voip call in android 10?
Over the lockscreen and all, just as a normal user would expect from a PHONE app.
Thanks in advance for any hints.
To open Activity over lock screen. you can use a high-notification with "full-screen intent" as CommonsWare's answer. But for more detail, you can try my solution as below code:
Create a foreground service then call buildNotification in onStartCommand method, the buildNotification method will return a notification which put into startForeground method parameter.
public class IncomingCallService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = buildNotification();
startForeground(1, notification);
return START_NOT_STICKY;
}
}
In buildNotification method, we will create notification with high priority, call category and a full screen intent.
private Notification buildNotification() {
Intent fullScreenIntent = new Intent(this, IncomingCallActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification_icon)
.setContentTitle("Incoming call")
.setContentText("(919) 555-1234")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
// Use a full-screen intent only for the highest-priority alerts where you
// have an associated activity that you would like to launch after the user
// interacts with the notification. Also, if your app targets Android 10
// or higher, you need to request the USE_FULL_SCREEN_INTENT permission in
// order for the platform to invoke this notification.
.setFullScreenIntent(fullScreenPendingIntent, true);
notificationBuilder.setAutoCancel(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.createNotificationChannel(new NotificationChannel("123", "123", NotificationManager.IMPORTANCE_HIGH));
notificationBuilder.setChannelId("123");
}
Notification incomingCallNotification = notificationBuilder.build();
return incomingCallNotification;
}
In onStartCommand, add a line of code to send ACTION_CLOSE_SYSTEM_DIALOGS broadcast action. This verify IMPORTANT to kick off full screen pending intent.
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = buildNotification();
startForeground(1, notification);
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
return START_NOT_STICKY;
}
Create full screen activity which you want to display over lock screen then you need to add setShowWhenLocked and setTurnScreenOn for display over lock screen. If not, your activity will be displayed behind lock screen. Below is my sample.
public class IncomingCallActivity extends AppCompatActivity {
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_explore);
setShowWhenLocked(true);
setTurnScreenOn(true);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
}
}
Now you must start IncomingCallService when you receive a call from your logic.
public void startCallService() {
Intent intent = new Intent(context, IncomingCallService.class);
startForegroundService(intent);
}
You must declare activity, service and some permission in your manifest as below:
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
...>
<activity android:name=".IncomingCallActivity" />
<service
android:name=".IncomingCallService"
android:enabled="true"
android:exported="true" />
</application>
I tested on google, samsung, vsmart phone. It work well. But for xaomi device. you need to enable some permission by flow below steps:
Long click to you app icon
Open app info
Click to "Other permission" item
Allow show on Lock screen
Now your app will work on xaomi device. If you face any problems with my solution, please leave a comment here. I will help you If I could.
Use a high-priority notification with a "full-screen intent". That will:
Invoke your "full-screen intent" if the device is locked
Otherwise, display a "heads-up" notification
Please go through my blog on how to open activity for OS 10 and also how to display heads up notification and handle clicks on the action buttons.
https://medium.com/#dcostalloyd90/show-incoming-voip-call-notification-and-open-activity-for-android-os-10-5aada2d4c1e4
Check this link this will help you
here
or
You need to ask for a permission "draw over other app" then you can make this as previous versions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (!Settings.canDrawOverlays(this)) {
RequestPermission();
}
}
private void RequestPermission() {
// Check if Android P or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + BuildConfig.APPLICATION_ID));
startActivityForResult(intent,
ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
or You can use my this answer
https://stackoverflow.com/a/63699960/7108113

How to keep the device sensor awake?

Using sensors I am detecting motion for some calculations for which I register sensors on a Service.
sensorManager.registerListener(sensorListener, sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION), SensorManager.SENSOR_DELAY_NORMAL);
For this, I am already using a foreground service with notifications to keep the sensor active.
Below is the code I used on the Service class (with higher priority for notification which returns sticky).
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
registerSensor();
Notification notification = new NotificationCompat.Builder(this, ServiceNotification.CHANNEL_1_ID)
.setSmallIcon(R.drawable.ic_stat_name)
.setPriority(NotificationCompat.PRIORITY_HIGH)
//.setCategory(NotificationCompat.CATEGORY_SERVICE)
//.setOngoing(true)
//.setAutoCancel(true)
//.setOnlyAlertOnce(true)
.setColor(getResources().getColor(R.color.colorPrimaryDark))
.setContentIntent(pendingIntent)
.build();
startForeground(13, notification);
return START_STICKY;
}
Android System doesn't kill my app, it runs whole night. But sensor doesn't response until I turn on the screen.
Tried acquiring Wakelock which solves my issue.
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MService: WakeLock");
mWakeLock.acquire();
But I don't want to use WakeLock for such long time.
Is there a way by which I can keep the phone's sensors alive for the long run, or am I doing something wrong with my foreground service/notification?
However, I researched a lot on foreground service with higher priorities.

Wake the Android Screen after a timer fires

How can I have a timer fire a method to wake up the screen of an Android device?
I inserted this:
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
into the
#Override
protected void onCreate(Bundle savedInstanceState) {
method.
Additionally, I made a timer after a user clicks a button which runs the following program:
final int interval = 3000; // 3 Seconds
Handler handler = new Handler();
Runnable runnable = new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(), "Here", Toast.LENGTH_SHORT).show();
}
};
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);
I want to be able to click the power button of my Android device to sleep it within the 3 second interval and have it wake up after the run() gets fired.
What do I call to trigger the screen to turn on?
This method also instantly turns on the screen:
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock TempWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK|PowerManager.ACQUIRE_CAUSES_WAKEUP, "TempWakeLock");
TempWakeLock.acquire();
TempWakeLock.release();
try to add to onCreate() :
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
wakeLock.acquire();
To release the screen lock:
KeyguardManager keyguardManager = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
keyguardLock.disableKeyguard();
Add to the manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

How to obtain a partial wake lock for an inline broadcast receiver

I have a receiver , that would receive a broadcast in future from an intentservice .
I have initialized the receiver inside my activity .
Sometimes the IntentService takes a while to complete, so by the time it broadcasts its result , the cellphone device is sleeping , so the broadcast is not received.
I have confirmed that even if the cellphone is sleeping , the IntentService runs to completion , only the broadcast receiver doesn't receive anything .
I know that I have to obtain a partial wake lock somehow and somewhere :( . I am in the dark about this .
This is my simple activity , with the only the relevant parts only .
public class NewsActivity extends Activity implements OnDownloadComplete{
...
..
..
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
..
System.out.println("Called"); // Not printed on logcat if the cell is sleeping
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_news);
..
..
..
/*LAUNCHING SERVICE*/
Intent intent = new Intent(context, NewsSyncTask.class);
intent.putExtra( NewsSyncTask.NOTIFICATION, Footer.this.receiverNotificationClass);
context.startService(intent);
}
}
Please help .
BroadcastReceiver should receive broadcast, you can try in this way first wright a separate class and extend it with BroadcastReceiver declare your BroadcastReceiver in menifest.xml under reciver tag, you should set intent filter to it so that it should listen only the broadcast which your intent service dose.
Use AlarmManager with a _WAKEUP-style alarm. Here is a sample project illustrating its use (along with a WakefulIntentService you will want, to make sure the device does not fall back asleep during your network I/O).
Try something like this :
MainActivity:
PowerManager pm = (PowerManager) this
.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
//Start the Service
wl.release();

skip the screenlock

protected void onPause()
{
super.onPause();
// If the screen is off then the device has been locked
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
boolean isScreenOn = powerManager.isScreenOn();
//screen locked
if (!isScreenOn) {
boolean pressed = onKeyDown(26, null);
//power button pressed
if(pressed){
//remove keyguard
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
//start intent
Intent i = new Intent(this, VoiceRecognitionActivity.class);
startActivity(i);
}
}
}
the above code does is when power button is pressed, the keyguard will be dismissed and the activity onpaused will be resumed.
However, the keyguard is not dimissed when i pressed the power button, and i have to unlock manually.
When i pressed the power button, the window of my activity flashed for a second and the keyguard window is shown.
If you want to prevent phone from turning screen off (and locking the phone in result) you should use WakeLock. You can use PowerManager.newWakeLock() with FLAG_KEEP_SCREEN_ON or even
FULL_WAKE_LOCK.
This code snippet may help:
final Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
// Turn on the screen unless we are being launched from the AlarmAlert
// subclass.
final boolean screenOff = getIntent().getBooleanExtra(SCREEN_OFF, false);
if (!screenOff) {
try {
// API 8+
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
} catch (final Throwable whocares) {
// API 7+
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
}

Categories

Resources