Android lint warns on the following with [Wakelock]:
public static void acquire(Context ctx, long timeout) {
if (wakeLock != null) {
wakeLock.release();
}
PowerManager powerManager
= (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE,
Common.TAG);
wakeLock.setReferenceCounted(false);
if ( timeout <= 0 ) {
wakeLock.acquire();
} else {
wakeLock.acquire(timeout);
}
}
public static synchronized void release() {
if ( wakeLock != null ) {
if ( wakeLock.isHeld() ) {
wakeLock.release();
}
wakeLock = null;
}
}
It gives the warning for the first occurrence
[lint] [...]/WakeLocker.java: Warning: The release() call is not always reached [Wakelock]
Yet, it does not really need to be released every time, as there is a timeout.
The default solution of wrapping this in a try-catch-block, as for example in android-wakelock-not-released-after-getactivenetworkinfo, or in #rainash's answer below, do not address the problems that led to using this approach, namely that the device can go back to sleep.
How is this fixed? Or should it be ignored?
use try-catch block wrap task you execute when device awake
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "tag");
wakeLock.acquire();
try {
do something
} finally {
wakeLock.release();
}
});
Indeed this seems to be a long forgotten problem. In fact this bug was reported to google already back in 2013 here, but seems to still be there.
As one commenter states:
The following code get the warning:
try {
wakeLock.acquire();
...
} catch (Exception e) {
...
} finally {
wakeLock.release();
}
Results in:
The release() call is not always reached (via exceptional flow)
However, if you throw the Exception in a method, no warning is reported:
private void makeMistake() throws Exception {
throw new Exception();
...
try {
wakeLock.acquire();
makeMistake();
} catch (Exception e) {
...
} finally {
wakeLock.release();
}
}
To disable this warning, rather do it in your apps build.gradle file, for easy access, rather than inline as suggested by #user.
...
lintOptions {
disable 'Wakelock'
}
As #tyczj hinted:
[Lint] also flags issues that may or may not be a problem depending on the context.
So think about the warning, and
If you've manually verified that an issue is not a problem, you may
want to mark the issue as verified such that lint does not keep
pointing it out.
To remove the warning in this case, use
#SuppressLint("Wakelock")
public static void acquire(Context ctx, long timeout) {
with
import android.annotation.SuppressLint;
Related
I am receiving a push notification, On that, calling a foreground service.
From the service, I am calling one Activity.
Here, I have 2 functionality.
1. Sound alarm for emergency
2. Call using ACTION_CALL.
Both are working fine if device unlocked.
But if a device is locked with password or pattern it did not work when push receives.
Below code to unlock the device. this method is called from onStart.
private void unlockDevice() {
KeyguardManager loKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
Window loWindow = this.getWindow();
if (Common.isAboveAPI27()) {
setShowWhenLocked(true);
setTurnScreenOn(true);
} else if (Common.isAboveAPI26()) {
loWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
loWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
dismissKeyguard(loKeyguardManager);
} else {
if (loKeyguardManager != null) {
KeyguardManager.KeyguardLock loKeyguardLock = loKeyguardManager.newKeyguardLock("FullWakeUps");
loKeyguardLock.disableKeyguard();
}
loWindow.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); // Deprecated in 26
loWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); // Deprecated in 27
loWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); // Deprecated in 27
}
//Keep screen on
loWindow.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void dismissKeyguard(KeyguardManager loKeyguardManager) {
if (loKeyguardManager != null) {
loKeyguardManager.requestDismissKeyguard(SOSCallAndAlarmActivity.this, new KeyguardManager.KeyguardDismissCallback() {
#Override
public void onDismissError() {
super.onDismissError();
Log.i(TAG, Build.VERSION.SDK_INT + " : onDismissError");
}
#Override
public void onDismissSucceeded() {
super.onDismissSucceeded();
Log.i(TAG, Build.VERSION.SDK_INT + " : onDismissSucceeded");
}
#Override
public void onDismissCancelled() {
super.onDismissCancelled();
Log.i(TAG, Build.VERSION.SDK_INT + " : onDismissCancelled");
}
});
}
}
The below method is call in onDestroy to reenable the lock:
private void reEnabledKeyguard() {
KeyguardManager loKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (loKeyguardManager != null) {
KeyguardManager.KeyguardLock loKeyguardLock = loKeyguardManager.newKeyguardLock("FullWakeUps");
loKeyguardLock.reenableKeyguard();
}
Window loWindow = this.getWindow();
loWindow.addFlags(WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
}
Code to initiate the call.
public void callOnNumbers(String fsPhoneNumber) {
Intent loCallIntent = new Intent(Intent.ACTION_CALL);
loCallIntent.setData(Uri.parse("tel:" + fsPhoneNumber));
//callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // tried this but not helped.
if (ActivityCompat.checkSelfPermission(CallAndAlarmActivity.this,
android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "call phone permission not granted");
return;
}
startActivity(loCallIntent);
}
Strange is when this method opens the call screen blink and again displays the password screen on lock screen simply press back button I can see the call screen.
I need to know one more thing, even I set all app killing option and disabled battery optimization. the same code did not execute on push receive.
When device inactive half an hour and if push receives, the above code did not even turn on light. when I click on the lock/unlock button I can see my screens properly. even I press it after 30 seconds of push receives time.
The problem facing from android N.
Additional
When the ACTION_CALL intent calls it to execute my activities onPause and I did not add any code in onPause and I can see one error in logcate
2020-04-27 16:23:47.400 25826-25826/app.safety E/ActivityThread: Performing stop of activity that is already stopped: {app.safety/app.safety.CallAndAlarmActivity}
java.lang.RuntimeException: Performing stop of activity that is already stopped: {app.safety/app.safety.CallAndAlarmActivity}
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4089)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4177)
at android.app.ActivityThread.-wrap24(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1648)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6687)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:810)
2020-04-27 16:23:47.400 25826-25826/app.safety E/ActivityThread: ActivityClientRecord{paused=true, stopped=true, hideForNow=false, startsNotResumed=false, isForward=false, pendingConfigChanges=0, onlyLocalRequest=false, preserveWindow=false, Activity{resumed=false, stopped=true, finished=false, destroyed=false, startedActivity=false, temporaryPause=false, changingConfigurations=false}}
Thanks
I wonder if it has something to do with the Background Execution Limit. in Android. I would recommend looking at this article.
https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c
I hope this is of any help.
I'm trying to get the current RSSI of a wifi connection in a Service using an AsyncTask. When the screen is turned off the value will not be updated until I turn the display back on again. So the value stays the same as the last value that was obtained before the display was turned off.
I used an Nexus 6P with Android O preview and a LG 3 with Android 6.
I'm obtaining a WakeLock and a WifiLock before via:
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiMeasureTaskWakeLock");
mWakeLock.acquire();
mWifiLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "WifiMeasureTaskWifiLock");
mWifiLock.acquire();
And in the doInBackground method I'm doing the following:
#Override
protected Void doInBackground(final Void... params) {
int dBm;
try {
//some other code here
while (true) {
if (isCancelled()) {
//some other code here
return null;
}
try {
//some other code here
//does not update when the screen if turned off
dBm = Math.max(mWifiManager.getConnectionInfo().getRssi(), -100);
//some other code here
}
} catch (IOException e) {
//some other code here
}
}
} catch (SocketException e) {
//some other code here
}
return null;
}
I already found an issue in the issue tracker but it's marked obsolete.
Does anybody know how to solve this problem?
I am trying billow Code from this answer to check if the permission is enabled. but it is returning false even when the permission is enabled from the settings.
public static boolean canDrawOverlayViews(Context con){
if(Build.VERSION.SDK_INT< Build.VERSION_CODES.LOLLIPOP){return true;}
try {
return Settings.canDrawOverlays(con);
}
catch(NoSuchMethodError e){
return canDrawOverlaysUsingReflection(con);
}
}
public static boolean canDrawOverlaysUsingReflection(Context context) {
try {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class clazz = AppOpsManager.class;
Method dispatchMethod = clazz.getMethod("checkOp", new Class[] { int.class, int.class, String.class });
//AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });
return AppOpsManager.MODE_ALLOWED == mode;
} catch (Exception e) { return false; }
}
Recently I've also faced the same issue and got the following workaround .
Referenced from
https://code.google.com/p/android/issues/detail?id=198671#c7
public boolean getWindoOverLayAddedOrNot2() {
String sClassName = "android.provider.Settings";
try {
Class classToInvestigate = Class.forName(sClassName);
if (context == null)
context = activity;
Method method = classToInvestigate.getDeclaredMethod("isCallingPackageAllowedToDrawOverlays", Context.class, int.class, String.class, boolean.class);
Object value = method.invoke(null, context, Process.myUid(), context.getPackageName(), false);
Log.i("Tag", value.toString());
// Dynamically do stuff with this class
// List constructors, fields, methods, etc.
} catch (ClassNotFoundException e) {
// Class not found!
} catch (Exception e) {
// Unknown exception
e.printStackTrace();
}
return false;
}
does the check involves the device admin?
I have encountered this problem when disabling device admin, I have checked this permission in the DeviceAdminReceiver->onDisabled() and on some devices, and canDrawOverlays returned false, despite the fact i had the permission.
The above answer helped sometimes but not all the time. the thing that did work is Thread.sleep before the check.
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// some exception here
}
The minimal time that worked for me was 20 millis. than canDrawOverlays returned true
Note: this is not a good practice however this is the only thing that worked for me
Based on BennyP's answer, I've made a Runnable run the required code after 500ms and that worked very well. The feedback is a bit delayed, but the user won't even notice the delay.
This is the code I've added to my onResume()
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(!Settings.canDrawOverlays(ControllerActivity.this)){
//Handle overlay permission not given here
}
else{
//Handle overlay permission given here
}
}
}, 500);
Hope it helps!
I tried restarting the activity after the user accessed the setting . This is code :
public static void restartActivity(Activity act){
Intent intent = getIntent();
finish();
startActivity(intent);
}
First of all, I am really very surprised with this strange behaviour of
Settings.canDrawOverlays(this);
I also faced the same issue with its usage, it was returning false even if the permission is already assigned.
What I noticed that, I was using this check in my onStart() method, where it was creating this wired behavior. To resolve this, I searched over internet and no result was there that can satisfy me and the one I can use.
Solution
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.e("Overlay Permission", "" + Settings.canDrawOverlays(this));
if (!Settings.canDrawOverlays(this)) {
MyPreferences.saveBoolean(HomeScreen.this, "showOverlayPermissionDialog", true);
} else {
MyPreferences.saveBoolean(HomeScreen.this, "showOverlayPermissionDialog", false);
}
}
I did something lake this, in my onCreate(). Here I saved the values accordingly in my SharedPreferences, and according to these Shared Preference values, I created a check for showing an overlay dialog in my onStart(). This worked fine!
You can try this solution, and mark this answer useful if your problem is solved.
Thanks
I am using this code to prevent dimming/locking screen, it is perfectly working for prevention of locking, but dimming effect is not prevented yet. please tell me some way out to prevent dimming also
protected void setScreenLock(boolean on){
if(mWakeLock == null){
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |
PowerManager.ON_AFTER_RELEASE, TAG);
}
if(on){
mWakeLock.acquire();
}else{
if(mWakeLock.isHeld()){
mWakeLock.release();
}
mWakeLock = null;
}
}
Add
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
View root = findViewById(android.R.id.content);
if (root != null)
root.setKeepScreenOn(true);
to your if part. This won't allow the screen to be dimmed.
Do not use WakeLock at all (remove your current code and you can also get rid of related permission from your Manifest file) - this is incorrect (in most cases) approach. Use FLAG_KEEP_SCREEN_ON flag in your onCreate() to tell framework to manage this for you. Doc reads:
Window flag: as long as this window is visible to the user, keep the
device's screen turned on and bright.
like this:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
I'm developing an Android application that might be used at night. Therefor, I need to turn off the buttons' backlight. How can I do this? On my own phone the backlight turns off after a while, but on the Motorola Droid I don't think this happens.
I'm using a wakelock to keep the screen on. Should I use another flag or how can I do this?
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, WAKE_LOCK_TAG);
mWakeLock.acquire();
Thank you very much!
//Kaloer
There is a hack:
private void setDimButtons(boolean dimButtons) {
Window window = getWindow();
LayoutParams layoutParams = window.getAttributes();
float val = dimButtons ? 0 : -1;
try {
Field buttonBrightness = layoutParams.getClass().getField(
"buttonBrightness");
buttonBrightness.set(layoutParams, val);
} catch (Exception e) {
e.printStackTrace();
}
window.setAttributes(layoutParams);
}
I see that this is an old question that was mostly answered in a comment link, but to make it clear to anyone else who comes across this question, here's my own answer.
It's built-in since API 8. (doc)
float android.view.WindowManager.LayoutParams.buttonBrightness
This is a somewhat modified/simplified version of what I'm using in one of my apps (excluding irrelevant code). The inner class is required to prevent a crash at launch on older platforms that don't support it.
private void nightMode() {
Window win = getWindow();
LayoutParams lp = win.getAttributes();
if (prefs.getBoolean("Night", false))
changeBtnBacklight(lp, LayoutParams.BRIGHTNESS_OVERRIDE_OFF);
else changeBtnBacklight(lp, LayoutParams.BRIGHTNESS_OVERRIDE_NONE);
win.setAttributes(lp);
}
private void changeBtnBacklight(LayoutParams lp, float value) {
if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
try {
new BtnBrightness(lp, value);
} catch (Exception e) {
Log.w(TAG, "Error changing button brightness");
e.printStackTrace();
}
}
}
private static class BtnBrightness {
BtnBrightness(LayoutParams lp, float v) {
lp.buttonBrightness = v;
}
}
AFAIK, there is no API to control the backlight of the buttons -- sorry!