android.view.WindowLeaked: error showing when alert dialog using - android

I have tried dismiss the alert dialog when the activity is destroyed.
#Override
public void onDestroy(){
super.onDestroy();
if (alertDialog != null && alertDialog.isShowing()) {
alertDialog.dismiss();
}
}
But I still got an error:
android.view.WindowLeaked: Activity com.Forewarn.ForewarnApp.activities.SignInActivity has leaked window DecorView#60f300f[] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:424)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:316)
at com.Forewarn.ForewarnApp.activities.SignInActivity.getFingerPrint(SignInActivity.java:713)
at com.Forewarn.ForewarnApp.activities.SignInActivity$8.onClick(SignInActivity.java:428)
at android.view.View.performClick(View.java:5612)
at android.view.View$PerformClick.run(View.java:22285)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
here is my activity:
if(AccountUtils.getIsTouch().equalsIgnoreCase("true")){
checkTouchId.setChecked(true);
checkTouchId.setVisibility(View.GONE);
txtTouchId.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Fingerprint API only available on from Android 6.0 (M)
keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
getFingerPrint();
} else {
Toast.makeText(getApplicationContext(),"Your Device does not have a Fingerprint Sensor",Toast.LENGTH_SHORT).show();
}
} else {
getFingerPrintHardware();
}
I'm getting error in below method : in this I'm using two alert dialogs .
public void getFingerPrint(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(!fingerprintManager.isHardwareDetected()){
/**
* An error message will be displayed if the device does not contain the fingerprint hardware.
* However if you plan to implement a default authentication method,
* you can redirect the user to a default authentication activity from here.
* Example:
* Intent intent = new Intent(this, DefaultAuthenticationActivity.class);
* startActivity(intent);
*/
Toast.makeText(getApplicationContext(),"Your Device does not have a Fingerprint Sensor",Toast.LENGTH_SHORT).show();
//textView.setText("Your Device does not have a Fingerprint Sensor");
} else {
// Checks whether fingerprint permission is set on manifest
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
//textView.setText("Fingerprint authentication permission not enabled");
Toast.makeText(getApplicationContext(),"Fingerprint authentication permission not enabled",Toast.LENGTH_SHORT).show();
} else{
// Check whether at least one fingerprint is registered
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!fingerprintManager.hasEnrolledFingerprints()) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(SignInActivity.this,R.style.DialogLevelsStyle);
alertDialogBuilder.setTitle("Touch ID isn't Set Up on This Device");
TextView myMsg = new TextView(this);
myMsg.setText("To set up Touch ID on this decice, go to Settings > Touch id & Passcode and add a valid fingerprint");
myMsg.setGravity(Gravity.CENTER_HORIZONTAL);
myMsg.setPadding(20,50,20,0);
myMsg.setTextColor(getResources().getColor(R.color.colorPrimary));
myMsg.setTextSize(15);
alertDialogBuilder.setView(myMsg);
//alertDialogBuilder.setMessage("Please place your fingertip on the scanner to verify your identity and Login");
alertDialogBuilder.setPositiveButton("Ok",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//finish();
//Toast.makeText(getApplicationContext(),"Hai",Toast.LENGTH_SHORT).show();
startActivityForResult(new Intent(Settings.ACTION_SETTINGS), 0);
}
});
alertDialog = alertDialogBuilder.create();
alertDialog.show();
//textView.setText("Register at least one fingerprint in Settings");
//Toast.makeText(getApplicationContext(),"Register at least one fingerprint in Settings",Toast.LENGTH_SHORT).show();
}else{
// Checks whether lock screen security is enabled or not
if (!keyguardManager.isKeyguardSecure()) {
//textView.setText("Lock screen security not enabled in Settings");
Toast.makeText(getApplicationContext(),"Lock screen security not enabled in Settings",Toast.LENGTH_SHORT).show();
}else{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(SignInActivity.this,R.style.DialogLevelsStyle);
alertDialogBuilder.setIcon(R.drawable.fingerprint);
alertDialogBuilder.setTitle("Touch Id for FOREWARN");
TextView myMsg = new TextView(this);
if(hiddenEmail == null){
myMsg.setText("Sign In with User Id "+userName);
}else {
myMsg.setText("Sign In with User Id "+hiddenEmail);
}
myMsg.setGravity(Gravity.CENTER_HORIZONTAL);
myMsg.setPadding(10,50,10,0);
myMsg.setTextColor(getResources().getColor(R.color.colorPrimary));
myMsg.setTextSize(16);
alertDialogBuilder.setView(myMsg);
//alertDialogBuilder.setMessage("Please place your fingertip on the scanner to verify your identity and Login");
alertDialogBuilder.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//finish();
Constant.isCanceled = "true";
}
});
alertDialog = alertDialogBuilder.create();
alertDialog.show();
generateKey();
if (cipherInit()) {
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
FingerprintHandler helper = new FingerprintHandler(this);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
}
}
}
}
}
}
I already added onDestroy method which is calling dailog.dismiss().
I'm confused to find out where I did wrong. Please help me.

leaked window DecorView#60f300f[] that was originally added
Above exceptions are coming if Dialogs are not dismiss() before
Activity is ended.
Add this onPause section.
#Override
public void onPause(){
super.onPause();
if (alertDialog != null && alertDialog.isShowing()) {
alertDialog.dismiss();
}
}
Rectify
if (cipherInit()) {
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
FingerprintHandler helper = new FingerprintHandler(this);
helper.startAuth(fingerprintManager, cryptoObject);
}
generateKey();
alertDialog = alertDialogBuilder.create();
alertDialog.show();

Generally, this issue happens when you are trying to show the dialog after your activity is destroyed, finished, onPause, ...
Some solutions:
Check if you are not calling the alertDialog.show(); in the same parent scope where you finish, pause or destroy your activity and try to control it.
for example, you've started another activity or process and then you try to show your dialog on the current activity
You can check if the activity is finished before calling the dialog if(!this.isFinishing()){//show your dialog} this for yourActivity
You can also use a small trick to check the state of your activity before starting a dialog. :
#Override protected void onPause() { isRunning = false; }
#Override protected void onResume() { isRunning = true; }

Related

Pause splash screen until user responds to permission request in android app

in my android application i have a splash screen that lasts 5 seconds during those 5 seconds i ask the user to grant location permission , I want to pause the splash screen activity until the user grants or denies the permission request.If the activity is not paused until the user responds, the next activity will be activated without having the user's response about the permission request here's my code
SpalshScreen activity:
public class SplashScreen extends BaseActivity {
private static int SPLASH_SCREEN_TIME_OUT = 6000;
some properties ....
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//will hide the title
getSupportActionBar().hide(); //hide the title bar
setContentView(R.layout.activity_splash_screen);
// This is the method that asks the user for permission
locationPermGranted = CheckLocationPermission();
deviceLanguage = Locale.getDefault().getDisplayLanguage();
DeviceLanguageCode = Locale.getDefault().getLanguage();
sharedPreferences = getSharedPreferences(getPackageName() + ".prefs", Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
codeIntent = new Intent(SplashScreen.this, PhoneVerification.class);
myIntent = new Intent(SplashScreen.this, ProfileSettings.class);
loggedIntent = new Intent(SplashScreen.this, Main.class);
notLoggedIntent = new Intent(SplashScreen.this, Login.class);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (!locationPermGranted) {
killApp();
}
if (sharedPreferences.getString("userLanguage", DeviceLanguageCode) == null) {
editor.apply();
}
if (sharedPreferences.getBoolean("isRegistered", false)) {
if (sharedPreferences.getBoolean("isPhoneVerified", false)) {
if (sharedPreferences.getBoolean("isLoggedIn", false)) {
// GO TO HOME
startActivity(loggedIntent);
} else {
// GO TO LOGIN
editor.apply();
startActivity(notLoggedIntent);
}
} else {
editor.apply();
startActivity(codeIntent);
}
} else {
//GO TO PROFILE SETTINGS
editor.apply();
startActivity(myIntent);
}
finish();
}
}, SPLASH_SCREEN_TIME_OUT);
}
Check the permission up front and if the permission is already granted, continue your Handler() and if not, then request for the permission and handle the result. Here's how:
Put all your Handler() code in a function so you can call it easily:
private void continueOperation(){
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (sharedPreferences.getString("userLanguage", DeviceLanguageCode) == null) {
editor.apply();
}
if (sharedPreferences.getBoolean("isRegistered", false)) {
if (sharedPreferences.getBoolean("isPhoneVerified", false)) {
if (sharedPreferences.getBoolean("isLoggedIn", false)) {
// GO TO HOME
startActivity(loggedIntent);
} else {
// GO TO LOGIN
editor.apply();
startActivity(notLoggedIntent);
}
} else {
editor.apply();
startActivity(codeIntent);
}
} else {
//GO TO PROFILE SETTINGS
editor.apply();
startActivity(myIntent);
}
finish();
}
}, SPLASH_SCREEN_TIME_OUT);
}
Here, you don't have to check for permission because this function will only be called
with granted permission.
Then, put a permission check in onCreate():
if (!locationPermGranted)
killApp();
else
continueOperation();
Now, handle the onRequestPermissionResult() and call continueOperation() if permission is granted.
In case, you don't want the user to wait for 6 seconds if the permission is granted in onRequestPermissionResult() which would obviously be bad UX, you can use the Handler() in the else{} of 2nd point. So, User will only have to wait if the permission was previously granted which is the basic purpose of a SplashScreen.
Surround newHandler().postDelayed method with if-else statement. If the user grants permission then only run the post delay method.

How to check MIUI autostart permission programmatically?

I need to check programmatically if the auto start permission for my app in MIUI phone is on or off. Facebook and whatsapp have this permission already enabled by default , how can I do so?
For now it's not possible.
As it's completely depend on their operating system API's and customisation. Even developers have requested for this on XIOMI's official forums but there is no response from there side.
Till now even i am finding an answer to this question but nothing helped me.
For the time being it will be only possible for rooted phones. i.e. making customisation in their firmware by becoming super user. But this is not at all advisable as it may damage user's phone.
EDIT 1
You can redirect user to autostart permission's settings page for enabling your app using following code
String manufacturer = "xiaomi";
if (manufacturer.equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
//this will open auto start screen where user can enable permission for your app
Intent intent1 = new Intent();
intent1.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent1);
}
EDIT 2
I have recently used Mi A1 from XIOMI which have stock android (not miui) so this phone does not have autostart permission settings from miui. So take care while navigating user to the settings in such devices because it will not work here.
100% working for oppo, vivo, xiomi, letv huawei, and honor
just call this function
private void addAutoStartup() {
try {
Intent intent = new Intent();
String manufacturer = android.os.Build.MANUFACTURER;
if ("xiaomi".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
} else if ("oppo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity"));
} else if ("vivo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
} else if ("Letv".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity"));
} else if ("Honor".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
}
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
startActivity(intent);
}
} catch (Exception e) {
Log.e("exc" , String.valueOf(e));
}
}
This is not a perfect solution by any means and it requires some testing, but I've been able to detect the autostart permission on my Xiaomi device with it.
The autostart permission allows apps to be started by receiving an implicit broadcast intent. This method consists of scheduling an implicit broadcast with AlarmManager, killing the app and checking if the broadcast caused it to respawn. A second explicit intent is also scheduled just to make sure that the app is started eventually.
public class AutostartDetector extends BroadcastReceiver {
// I've omitted all the constant declaration to keep this snippet concise
// they should match the values used in the Manifest
public static void testAutoStart(Context context) {
long now = System.currentTimeMillis();
// this ID is for matching the implicit and explicit intents
// it might be unnecessary
String testId = Long.toHexString(now);
Intent implicitIntent = new Intent(ACTION_IMPLICIT_BROADCAST);
// the category is set just to make sure that no other receivers handle the broadcast
implicitIntent.addCategory(CATEGORY_AUTOSTART);
implicitIntent.putExtra(EXTRA_TEST_ID, testId);
PendingIntent implicitPendingIntent =
PendingIntent.getBroadcast(context, REQUEST_CODE_IMPLICIT_BROADCAST, implicitIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent explicitIntent = new Intent(ACTION_EXPLICIT_BROADCAST);
explicitIntent.addCategory(CATEGORY_AUTOSTART);
explicitIntent.setComponent(new ComponentName(context, AutostartDetector.class));
explicitIntent.putExtra(EXTRA_TEST_ID, testId);
PendingIntent explicitPendingIntent =
PendingIntent.getBroadcast(context, REQUEST_CODE_EXPLICIT_BROADCAST, explicitIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// calling commit() makes sure that the data is written before we kill the app
// again, this might be unnecessary
getSharedPreferences(context).edit().putInt(testId, TestStatus.STARTED).commit();
// the explicit intent is set with an additional delay to let the implicit one be received first; might require some fine tuning
alarmManager.set(AlarmManager.RTC_WAKEUP, now + BASE_DELAY, implicitPendingIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP, now + BASE_DELAY + EXPLICIT_INTENT_DELAY, explicitPendingIntent);
// kill the app - actually kind of tricky, see below
SelfKiller.killSelf(context);
}
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences = getSharedPreferences(context);
String testId = intent.getStringExtra(EXTRA_TEST_ID);
if (testId == null) {
Log.w(TAG, "Null test ID");
return;
}
if (!sharedPreferences.contains(testId)) {
Log.w(TAG, "Unknown test ID: " + testId);
return;
}
String action = intent.getAction();
if (ACTION_IMPLICIT_BROADCAST.equals(action)) {
// we could assume right here that the autostart permission has been granted,
// but we should receive the explicit intent anyway, so let's use it
// as a test sanity check
Log.v(TAG, "Received implicit broadcast");
sharedPreferences.edit().putInt(testId, TestStatus.IMPLICIT_INTENT_RECEIVED).apply();
} else if (ACTION_EXPLICIT_BROADCAST.equals(action)) {
Log.v(TAG, "Received explicit broadcast");
int testStatus = sharedPreferences.getInt(testId, -1);
switch (testStatus) {
case TestStatus.STARTED:
// the implicit broadcast has NOT been received - autostart permission denied
Log.d(TAG, "Autostart disabled");
sharedPreferences.edit().putBoolean(PREF_AUTOSTART_ENABLED, false).apply();
notifyListener(false);
break;
case TestStatus.IMPLICIT_INTENT_RECEIVED:
// the implicit broadcast has been received - autostart permission granted
Log.d(TAG, "Autostart enabled");
sharedPreferences.edit().putBoolean(PREF_AUTOSTART_ENABLED, true).apply();
notifyListener(true);
break;
default:
Log.w(TAG, "Invalid test status: " + testId + ' ' + testStatus);
break;
}
}
}
private interface TestStatus {
int STARTED = 1;
int IMPLICIT_INTENT_RECEIVED = 2;
}
Receiver declaration in the manifest:
<receiver android:name=".autostart.AutostartDetector">
<intent-filter>
<category android:name="com.example.autostart.CATEGORY_AUTOSTART"/>
<action android:name="com.example.autostart.ACTION_IMPLICIT_BROADCAST"/>
<action android:name="com.example.autostart.ACTION_EXPLICIT_BROADCAST"/>
</intent-filter>
</receiver>
Killing the app reliably is another problem. I've been using this helper method:
public static void killSelf(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
activityManager.killBackgroundProcesses(context.getPackageName());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// this is all we can do before ICS. luckily Xiaomi phones have newer system versions :)
System.exit(1);
return;
}
// set up a callback so System.exit() is called as soon as all
// the activities are finished
context.registerComponentCallbacks(new ComponentCallbacks2() {
#Override
public void onTrimMemory(int i) {
if (i == TRIM_MEMORY_UI_HIDDEN) {
Log.v(TAG, "UI Hidden");
System.exit(1);
}
}
/* ... */
});
// see below
ActivityTracker.getInstance().finishAllActivities();
}
ActivityTracker is another utility that keeps track of activity lifecycles. Make sure to register it in the Application subclass.
#RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public final class ActivityTracker implements Application.ActivityLifecycleCallbacks {
private final ArraySet<Activity> mCreatedActivities = new ArraySet<>();
public static ActivityTracker getInstance() {
return Holder.INSTANCE;
}
public static void init(Application application) {
application.registerActivityLifecycleCallbacks(getInstance());
}
public static void release(Application application) {
ActivityTracker activityTracker = getInstance();
application.unregisterActivityLifecycleCallbacks(activityTracker);
activityTracker.mCreatedActivities.clear();
}
public void finishAllActivities() {
// iterate over active activities and finish them all
for (Activity activity : mCreatedActivities) {
Log.v(TAG, "Finishing " + activity);
activity.finish();
}
}
public Set<Activity> getCreatedActivities() {
return Collections.unmodifiableSet(mCreatedActivities);
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
mCreatedActivities.add(activity);
}
#Override
public void onActivityDestroyed(Activity activity) {
mCreatedActivities.remove(activity);
}
private static final class Holder {
private static final ActivityTracker INSTANCE = new ActivityTracker();
}
/* ... */
}
You might also want to stop all the services just to be sure.
In addition to Nikhil's answer:
First of all, some apps like Facebook, Whatsapp are whitelisted from Xiomi by default that means auto start permission will automatically be on for these apps.
I also didn't find any way to check for auto start permission if it's enabled or not and enable it programmatically. Though as above answer suggests we can redirect user to auto start permission activity but when we have to redirect user we still don't know and also this will not work in all of the Xiomi devices.
So I used an alternative for my sync adapter to work. I stored a boolean variable named "isSyncAdapterRunning" in shared preferences and set the value of it every time sync adapter runs. This way I'll be able to know if my sync adapter is working or not.
//in my sync adapter
#Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
Log.e("TAG", "SyncStarted");
performSync(true);
}
public static void performSync(boolean fromSyncAdapterClass){
//write your code for sync operation
if(fromSyncAdapterClass){
setValueOfIsSyncAdapterRunningVariable();
}
}
I made other background service to perform same task if sync adapter is not working.
//In my other background service
public class BackgroundSyncService extends IntentService {
public BackgroundSyncService() {
super("BackgroundSyncService");
}
#Override
protected void onHandleIntent(Intent intent) {
SyncAdapter.performSync(false);
}
}
Now start sync adapter:
// start your sync adapter here
//And after that just start that service with a condition
if(!getValueOfIsSyncAdapterRunningVariable()){
startService(new Intent(context, BackgroundSyncService.class));
}
So basically I'm running another service to perform same task in background if my sync adapter is not working and the best thing is only one of them will run at a time.
Above code will fail if user turn on auto start permission and turn off again because value of boolean variable is already set. For that you can set value of boolean variable to default once in every 24Hrs.
Hope this helps.
For now it's not possible.
As it's completely depend on their operating system API's and customization. But i implemented a fix using SharedPreference. It doesn't solved the problem but it prevents app from opening setting screen everytime app is opened. Example :
if (AppPref.getAutoStart(context).isEmpty() && AppPref.getAutoStart(context).equals("")) {
enableAutoStart();
}
private void enableAutoStart() {
if (Build.BRAND.equalsIgnoreCase("xiaomi")) {
new AlertDialog.Builder(context)
.setTitle("Enable AutoStart")
.setMessage("Please allow this app to always run in the background,else our services can't be accessed.")
.setNegativeButton("Deny", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
AppPref.setAutoStart(context, "");
dialog.dismiss();
}
})
.setPositiveButton("ALLOW", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
try {
AppPref.setAutoStart(context, "1");
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.miui.securitycenter",
"com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent);
} catch (Exception e) {
Toast.makeText(context, "Can't perform action", Toast.LENGTH_SHORT).show();
}
dialog.dismiss();
}
})
.create()
.show();
}
}
This code worked for me. Simple and easy . Credit
private State getAutoStartState(Activity activity) throws Exception {
Class<?> clazz;
try {
clazz = Class.forName(CLAZZ);
} catch (ClassNotFoundException ignored) {
// we don't know if its enabled, class
// is not found, no info
return State.NO_INFO;
}
final Method method = getMethod(clazz);
if (method == null) {
// exception raised while search the method,
// or it doesn't exist
return State.NO_INFO;
}
// the method is a public method, It's still
// better to do this
method.setAccessible(true);
// the target object is null, because the
// method is static
final Object result = method.invoke(null, getActivity(),
getActivity().getPackageName());
// the result should be an Int
if (!(result instanceof Integer))
throw new Exception();
final int _int = (int) result;
if (_int == ENABLED)
return State.ENABLED;
else if (_int == DISABLED)
return State.DISABLED;
return State.UNKNOWN;
}
private Method getMethod(Class<?> clazz) {
try {
return clazz.getDeclaredMethod("getApplicationAutoStart",
Context.class, String.class);
} catch (Exception ignored) {
// this should not happen, probably
// MIUI version is updated, lets give a last try
return null;
}
}
public void checkMIUIAutoStart(Activity activity) throws Exception {
if (getAutoStartState(activity) == State.DISABLED) {
String manufacturer = "xiaomi";
if (manufacturer.equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
//this will open auto start screen where user can enable permission for your app
Intent intent1 = new Intent();
intent1.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
startActivity(intent1);
}
}else {
Toast.makeText(activity, "Auto-start is enabled.", Toast.LENGTH_SHORT).show();
}
}
You cannot check whether autorun permission is enabled or not because autorun feature is provided by customised os only not by android os like mi, vivo, oppo, letv etc
This is a workaround tested on MI, Honor and vivo phones.
To check whether os is customised like miui, honor ui copy and paste this method in activity, fragment or util class
public static void getAutoStartPermission(final Activity context) {
final String build_info = Build.BRAND.toLowerCase();
switch (build_info) {
case "xiaomi":
Utilities.Companion.showAutorunDialog(context);
break;
case "letv":
Utilities.Companion.showAutorunDialog(context);
break;
case "oppo":
Utilities.Companion.showAutorunDialog(context);
break;
case "vivo":
Utilities.Companion.showAutorunDialog(context);
break;
case "Honor":
Utilities.Companion.showAutorunDialog(context);
break;
default:
break;
}
}
Where
fun showAutorunDialog(context: Context) {
val builder = AlertDialog.Builder(context)
//set title for alert dialog
builder.setTitle("Alert")
//set message for alert dialog
builder.setMessage("Enable Autostart permission for this app if its disabled in app settings in order to run application in background.")
builder.setCancelable(true)
//performing positive action
builder.setPositiveButton("Enable") { _, _ ->
addAutoStartup(context)
}
// Create the AlertDialog
var vpnDialog = builder.create()
// Set other dialog properties
vpnDialog!!.setCancelable(false)
vpnDialog!!.show()
}
private fun addAutoStartup(context:Context) {
try {
val intent = Intent()
val manufacturer = Build.MANUFACTURER
if ("xiaomi".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")
} else if ("oppo".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")
} else if ("vivo".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")
} else if ("Letv".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")
} else if ("Honor".equals(manufacturer, ignoreCase = true)) {
intent.component = ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")
}
val list: List<ResolveInfo> = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
if (list.size > 0) {
context.startActivity(intent)
}
} catch (e: java.lang.Exception) {
Log.e("exc", e.toString())
}
}
You could use this library to check the autostart permission state on MIUI 10, 11 and 12.
https://github.com/XomaDev/MIUI-autostart
// make sure device is MIUI device, else an
// exception will be thrown at initialization
Autostart autostart = new Autostart(applicationContext);
State state = autostart.getAutoStartState();
if (state == State.DISABLED) {
// now we are sure that autostart is disabled
// ask user to enable it manually in the settings app
} else if (state == State.ENABLED) {
// now we are also sure that autostart is enabled
}
To check if permission enabled, I just starting a foreground service and check if is running.
Service:
class ExtraPermissionStateService: Service() {
companion object {
private var instance: ExtraPermissionStateService? = null
fun isAppCanRunOnBackground(context: Context): Boolean {
val serviceIntent = Intent(context, ExtraPermissionStateService::class.java)
context.startService(serviceIntent)
return instance != null
}
}
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
instance = this
}
override fun onDestroy() {
super.onDestroy()
instance = null
}
}
call it:
ExtraPermissionStateService.isAppCanRunOnBackground(context)
And don't forget on the manifest:
<service android:name=".helpers.utils.ExtraPermissionStateService"/>
I have tried the below solution and it worked for me. If the "Auto Start" is enabled it will return "true", if not it will return "false".
public class CustomPermissionCheck {
private static final String TAG = "CustomPermissionCheck";
private Context context;
private static final int APP_AUTO_START_PERMISSION_CODE = 10008;
public CustomPermissionCheck(Context context) {
this.context = context;
}
public boolean isAutoStartEnabled() {
try {
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Method method = AppOpsManager.class.getMethod("checkOpNoThrow", int.class, int.class, String.class);
int result = (int) method.invoke(appOpsManager, APP_AUTO_START_PERMISSION_CODE, android.os.Process.myUid(), context.getPackageName());
boolean isEnabled = result == AppOpsManager.MODE_ALLOWED;
return isEnabled;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
You have to do allow and deny for system permissions.
below is the code:
private boolean checkPermission(){
int result = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Snackbar.make(view,"Permission Granted, Now you can access location data.",Snackbar.LENGTH_LONG).show();
} else {
Snackbar.make(view,"Permission Denied, You cannot access location data.",Snackbar.LENGTH_LONG).show();
}
break;
}
}

IF Else Error in Android application

This if-else statement I am using it onClick method of Android code.
if (input == null){
dispError();
}else{
startAct();
}
when value is true or false startAct() gets implemented;
if (input != null){
dispError();
}else{
startAct();
}
when value is true or false dispError() gets implemented;
input is a string.
actual code of my program:
#Override
public void onClick(View view) {
// Launching Display Meaning Activity
meaning = (EditText) findViewById(R.id.editText1);
input = meaning.getText().toString();
if (input == null){
dispError();
}else{
startAct();
}
}
public void startAct(){
Intent intent =new Intent("com.dictionary.khasi_english.DisplayMeaningActivity");
intent.setClass(MainActivity.this, DisplayMeaningActivity.class);
intent.putExtra(MEANING_INPUT, input);
startActivity(intent);
}
public void dispError(){
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("ERROR");
builder.setMessage("Please enter a Word.")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
}
});
}
}
meaning.getText().toString() will never return null. However, it can return "", an empty string. Use the following code to check against that:
if(input.isEmpty()) {
dispError();
else {
startAct();
}
It is because input, as you said, could be 'true' or 'false'. In both cases input is not null. If you want your if-statement works, you should try:
if(input.equals("true")) {
startAct();
else {
dispError();
}
Assuming you are trying to check whether the user put in any text, you should use TextUtils.isEmpty, which checks against both null and empty strings:
if(TextUtils.isEmpty(input)) {
dispError();
} else {
startAct();
}
if input is a string
try to use input.length to check if it is empty
if(input.length==0)
displayerror();
because if input=""then it is not null.
you can use TextUtils.isEmpty()

Android API to check if call is Active or On Hold

Is there an API function to check if a call is currently Active, or if has been put on Hold?
Assuming I have two connected calls, is there a way to check if each one is active, on-hold, or maybe they are connected in a conference call?
Yes, you can check if a call is active over device or not:
public static boolean isCallActive(Context context){
AudioManager manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
if(manager.getMode()==AudioManager.MODE_IN_CALL){
return true;
}
else{
return false;
}
}
This is proper way:
Add a permission to manifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Request permission from the user:
private boolean runThisWhileStartingApp() {
boolean hasPhonePermission = checkPermission(android.Manifest.permission.READ_PHONE_STATE, "Explantation why the app needs this permission");
if (!hasPhonePermission) {
// user did not allow READ_PHONE_STATE permission
}
}
private boolean checkPermission(final String permissionName, String reason) {
if (ContextCompat.checkSelfPermission(MyActivity.this, permissionName) != android.content.pm.PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MyActivity.this, permissionName)) {
AlertDialog alertDialog = new AlertDialog.Builder(MyActivity.this).create();
alertDialog.setTitle(permissionName);
alertDialog.setMessage(reason);
alertDialog.setCancelable(false);
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ActivityCompat.requestPermissions(MyActivity.this, new String[]{ permissionName }, 1000);
}
});
alertDialog.show();
} else {
ActivityCompat.requestPermissions(InitActivity.this, new String[]{ permissionName }, 1000);
}
return false;
}
return true;
}
And finally, check if device handles ongoing call anytime:
TelecomManager tm = (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
boolean isInCall = tm.isInCall(); // true if there is an ongoing call in either a managed or self-managed ConnectionService, false otherwise
Documentation: https://developer.android.com/reference/android/telecom/TelecomManager#isInCall()

Trying to lock screen rotation when displaying dialogs

I am trying to lock my screen in whatever orientation the user is in when the application launches a dialog and then unlocking it when the dialog dismisses. Here is my lock and unlock code:
// Sets screen rotation as fixed to current rotation setting
private void mLockScreenRotation() {
Log.d("####################", "screen orientation is " + mContext.getResources().getConfiguration().orientation);
// Stop the screen orientation changing during an event
if (mContext.getResources().getConfiguration().orientation == 1)
((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
else ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// switch (mContext.getResources().getConfiguration().orientation)
// {
// case Configuration.ORIENTATION_PORTRAIT:
// ((Activity) mContext).setRequestedOrientation(
// ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// break;
// case Configuration.ORIENTATION_LANDSCAPE:
// ((Activity) mContext).setRequestedOrientation(
// ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// break;
// }
}
// allow screen rotations again
private void mUnLockScreenRotation() {
this.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
mIsScreenRotationLocked = false;
}
I call mLockScreenRotation() when I launch any dialogs and I call mUnlockScreenRotation() in my handler and in my DialogInterface.OnClickListener's.
Sometimes my screen remains locked, but it is not consistent. Any suggestions or ideas why or how to handle this?
Thanks in advance for any help!
Ammendment: code where I am locking my screen:
public void displayProgressDialog(){
mLockScreenRotation();
// Get local handle on class progress dialog for optimization purposes
ProgressDialog temp = mProgressDialog = new ProgressDialog(this);
// Get message string (for some reason this dialog can't handle res IDs for messages)
String message = getString(R.string.downloading);
// Set some paramaters
temp.setIndeterminate(true);
temp.setTitle(R.string.weather_data);
temp.setMessage(message);
temp.setCancelable(false);
temp.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS /*WindowManager.LayoutParams.FLAG_BLUR_BEHIND*/);
temp.show();
}
public void displayLocationSearchDialog(){
mLockScreenRotation();
// Get local handle on class progress dialog for optimization purposes
ProgressDialog temp = mCoordinateSearchDialog = new ProgressDialog(this);
// Get message string (for some reason this dialog can't handle res IDs for messages)
String message = getString(R.string.searching);
// Set some paramaters
temp.setIndeterminate(true);
temp.setTitle(R.string.location_search);
temp.setMessage(message);
temp.setCancelable(false);
temp.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
temp.show();
}
public void showDatafeedFailedDialog(){
mLockScreenRotation();
new AlertDialog.Builder(this)
.setTitle(R.string.network_error)
.setMessage(R.string.weather_data_failed)
.setPositiveButton(R.string.try_again, mTryAgainListener)
.setNegativeButton(R.string.dismiss, null)
.create()
.show();
}
public void showCoordinateSearchFailedDialog(){
mLockScreenRotation();
new AlertDialog.Builder(this)
.setTitle(R.string.network_error)
.setMessage(R.string.location_search_failed)
.setPositiveButton(R.string.try_again, mCoordTryAgainListener)
.setNegativeButton(R.string.dismiss, null)
.create()
.show();
}
private void showGpsAlertDialog(){
mLockScreenRotation();
new AlertDialog.Builder(this)
.setTitle(R.string.gps_error)
.setMessage(R.string.gps_error_details)
.setNeutralButton(R.string.dismiss, null)
.setPositiveButton(R.string.go_to_settings, mToSettingsListener)
.create()
.show();
}
private void showGpsSearchingDialog(){
mLockScreenRotation();
ProgressDialog temp = mGpsSearchAlertDialog = new ProgressDialog(this);
String message = getString(R.string.location_services_details);
String btnText = getString(R.string.cancel);
temp.setIndeterminate(true);
temp.setTitle(R.string.location_services);
temp.setMessage(message);
temp.setButton(btnText, mCancelGpsSearchListener);
temp.setCancelable(true);
temp.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
temp.show();
}
private void showGpsTimeoutAlertDialog(){
mLockScreenRotation();
new AlertDialog.Builder(this)
.setTitle(R.string.gps_error)
.setMessage(R.string.gps_timeout_message)
.setPositiveButton(R.string.try_again, mGpsTimeoutListener)
.setNegativeButton(R.string.dismiss, mGpsTimeoutListener) // check this line with free if still no good
.create()
.show();
}
private void showWeatherAlertDialog(){
Log.d("############", "weather alert dialog");
mLockScreenRotation();
String message = null;
if(mWD.getWarningTypes() == null) return;
int cnt = 0;
int size = mWD.getWarningTypes().size() - 1;
for(String warningType : mWD.getWarningTypes()){
if(cnt == 0) message = warningType;
else if(cnt == size) message += " and " + warningType;
else message += ", " + warningType;
cnt++;
}
new AlertDialog.Builder(this)
.setTitle(R.string.watches_and_warnings)
.setMessage(message)
.setPositiveButton(R.string.go_to_accuweather, mToAlertWebListener)
.setNeutralButton(R.string.dismiss, null)
.create()
.show();
}
private void showNeedLocationAlertDialog() {
mLockScreenRotation();
new AlertDialog.Builder(this).setTitle(R.string.error).setMessage(
R.string.add_location).setNeutralButton(R.string.dismiss, null)
.setPositiveButton(R.string.okay, mToLocationSearchListener)
.create().show();
}
private void showConnectivityAlertDialog() {
mLockScreenRotation();
new AlertDialog.Builder(this).setTitle(R.string.network_error)
.setMessage(R.string.no_connection).setNeutralButton(
R.string.dismiss, null).create().show();
}
private void showCurrentUrlInBrowser(){
// Show current conditions web page
if(mWD.getURL() == null || mWD.getURL().length()
This is a bad solution, but it works. Tested on LG GT540(Android 2.3.7) and Asus Transformer(Android 3.2):
private void stopRotate()
{
if(getResources().getConfiguration().orientation == 1)
{
if( display.getOrientation() == 1 || display.getOrientation() == 2)
setRequestedOrientation(9);
else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else
{
if( display.getOrientation() == 2 || display.getOrientation() == 3)
setRequestedOrientation(8);
else
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
private void startRotate()
{
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
Instead of putting the call to change orientation within the dialog (and then presumably dismissing said dialog immediately afterwards), try implementing onDismiss listener to your Dialog, as outlined here.

Categories

Resources