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?
Related
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
Im making an apps that mock location and executing set ALLOW_MOCK_LOCATION turned on and off on runtime, so i hopes the other apps which detecting the ALLOW_MOCK_LOCATION flag will never get the ALLOW_MOCK_LOCATION as 1(true).
I read from here that it was possible and said to be fast enough, so other apps can hardly detect the change of ALLOW_MOCK_LOCATION. But what i am get is the other apps still sometimes reed ALLOW_MOCK_LOCATION as 1(true).
Please note that my devices already rooted and i can confirm it does mocked the location well. I also tried move it into /system/app, but still also encounter this problem.
This is the periodical loop which dispatch a asyntask with timeout(I even set the timeout 3 millis !!).
while(RUNNING){
fakeLocation.setAltitude(65.0);
fakeLocation.setAccuracy(Criteria.ACCURACY_FINE);
fakeLocation.setSpeed(0.0f);
fakeLocation.setTime(System.currentTimeMillis());
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
fakeLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
if(locationJellyBeanFixMethod!=null){
try {
locationJellyBeanFixMethod.invoke(fakeLocation);
}catch(Exception ex){}
}
}
new Thread(new Runnable() {
#Override
public void run() {
try {
new MockTask().execute().get(3, TimeUnit.MILLISECONDS);
}catch(TimeoutException e){
changeMockLocationSettings(0);
//Log.d(GLOBAL_VAR.TAG_DEBUG,"Mock location timeout:");
}catch(Exception e){}
}
}).start();
try {Thread.sleep(1500);} catch (InterruptedException e) {}
}
Below is the Asyntask
private class MockTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... param) {
try {
changeMockLocationSettings(1);
locationManager.setTestProviderLocation(GLOBAL_VAR.PROVIDER_NAME, fakeLocation);
changeMockLocationSettings(0);
//Log.d(GLOBAL_VAR.TAG_DEBUG,"location mocked -> "+fakeLocation);
} catch (Exception ex) {
//Log.d(GLOBAL_VAR.TAG_DEBUG,"Failed to mock location:"+ex.toString());
}
return null;
}
#Override
protected void onPostExecute(Void loc) {}
}
And lastly, the method to change ALLOW_MOCK_LOCATION
private boolean changeMockLocationSettings(int value) {
try {
return Settings.Secure.putInt(getApplicationContext().getContentResolver(),Settings.Secure.ALLOW_MOCK_LOCATION, value);
} catch (Exception e) {
Log.d(GLOBAL_VAR.TAG_DEBUG,"Setting allow mock location to "+value+" failed :"+e.toString());
e.printStackTrace();
return false;
}
}
Please help and correct me, and even suggest a better solution if any, and thanks in Advance
today i create a app in map , but it crash when battery saver is on .
How to check event when battery saver in on, for every device, help me. Thanks
i try this, but not working in API <21:
PowerManager powerManager = (PowerManager)
this.getSystemService(Context.POWER_SERVICE);
if ( powerManager.isPowerSaveMode()) {
// Animations are disabled in power save mode, so just show a toast instead.
Toast.makeText(customer_textReport.this, "Vui lòng tắt chế độ tiết kiệm pin", Toast.LENGTH_SHORT).show();
}
else {
Intent intentvitri = new Intent(customer_textReport.this, CustomerGetLocation.class);
startActivityForResult(intentvitri, 111);
}
Check Google Developer: PowerManager
In the left top, you can change API level.
As you can see, isPowerSaveMode(), is added in API 21(Lollipop).
So it won't work on older devices.
On Mobiles with an Android version below 5.0 (Lollipop) the power_saving mode is different for each manufactor. However if your target version is 5.0 and higher you can use the PowerManager as descripted in Android Developer
Hmm.This is check high acurary mode in GPS. This is check:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
if (getLocationMode(getApplicationContext()) != 3) {
tvmessage.setText("Please turn on GPS high Acurary");
btcancel_Dialog.setText("OK");
btcancel_Dialog.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
dlg.dismiss();
}
});
dlg.show();
} else {
Intent intentvitri = new Intent(customer_textReport.this, CustomerGetLocation.class);
startActivityForResult(intentvitri, 111);
}
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
}
and method getLocationMode return mode of GPS:
private int getLocationMode(Context context) throws Settings.SettingNotFoundException {
return Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
}
I ended up with this function.
Note: It's not equal to isPowerSaveMode(). It's more like isRunningOutOfPower() or couldBePowerSaveMode()
It checks if the SDK >= 21 then isPowerSaveMode function is available. if not, then check if the GPS mode is not HIGH_ACCURACY and battery level is less than 15% then it "could be" powerSaveMode.
public static boolean couldBePowerSaveMode(Context context) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (powerManager != null) {
return powerManager.isPowerSaveMode();
}
}
if (getLocationMode(context) != Settings.Secure.LOCATION_MODE_HIGH_ACCURACY) {
return getBatteryPercentage(context) <= 15;
}
return getBatteryPercentage(context) <= 15;
}
Try this (ready for copy/paste):
/**
* Checks if device is in power save mode. For older versions that do not support this API, returns false.
* #return true if it is, false otherwise.
*/
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean isPowerSaveMode(Context context)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
return powerManager.isPowerSaveMode();
}
// For older versions, we just say that device is not in power save mode
return false;
}
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;
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!