Opencv stopped working on Android 6.0 - android

I am using Opencv on my application and it works fine with Android 4.3 but it doesn't even open with Android 6.0.
I looked up for a solution on SO, and found one that says to set the package name. So I did it.
Follow code:
public static boolean initOpenCV(String Version, final Context AppContext,
final LoaderCallbackInterface Callback)
{
AsyncServiceHelper helper = new AsyncServiceHelper(Version, AppContext, Callback);
Intent intent = new Intent("org.opencv.engine.BIND");
intent.setPackage("org.opencv.engine");
if (AppContext.bindService(intent,
helper.mServiceConnection, Context.BIND_AUTO_CREATE))
{
return true;
}
else
{
AppContext.unbindService(helper.mServiceConnection);
InstallService(AppContext, Callback);
return false;
}
}
But now I am getting the following error:
11-18 10:14:43.447 24901-24930/br.com.ibramed.dermos E/AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
11-18 10:14:43.447 24901-24930/br.com.ibramed.dermos E/AndroidRuntime: at android.view.ViewRootImpl.setView(ViewRootImpl.java:571)
11-18 10:14:43.447 24901-24930/br.com.ibramed.dermos E/AndroidRuntime: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:310)
11-18 10:14:43.447 24901-24930/br.com.ibramed.dermos E/AndroidRuntime: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
11-18 10:14:43.447 24901-24930/br.com.ibramed.dermos E/AndroidRuntime: at android.app.Dialog.show(Dialog.java:319)
in the following code:
case InstallCallbackInterface.NEW_INSTALLATION:
{
Looper.prepare();
Log.d("Debug", ""+mAppContext);
AlertDialog InstallMessage = new AlertDialog.Builder(mAppContext).create();
InstallMessage.setTitle("Package not found");
InstallMessage.setMessage(callback.getPackageName() + " package was not found! Try to install it?");
InstallMessage.setCancelable(false); // This blocks the 'BACK' button
InstallMessage.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", new OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
callback.install();
}
});
InstallMessage.setButton(AlertDialog.BUTTON_NEGATIVE, "No", new OnClickListener() {
public void onClick(DialogInterface dialog, int which)
{
callback.cancel();
}
});
InstallMessage.show();
} break;
I have searched and found some people saying to keep track of the main Context, because Threads doesn't have context. But my app already does this and use the main context to create the AlertDialogs and it still doesn't work.
The error is when the app show the AlertDialog.
I really don't know what else to do. Can someone help?

As far as I know in service or Aplication class you cant get context with View for android 6.0, so when OpenCv tries to show AlertDialog it does not know to what activity bind dialog and crashes.
Try to init OpenCv in Activity onCreate method before usage.
My working init method in MainActivity (code on kotlin):
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, object : BaseLoaderCallback(this#HistoryActivity) {
override fun onManagerConnected(status: Int) {
if (LoaderCallbackInterface.SUCCESS == status)
Log.i(TAG, "OpenCV was loaded")
else
super.onManagerConnected(status)
}
})
}

Related

BiometricPrompt in android is not supporting exit on back button

I am using android provided BiometricPrompt class to provide Biometric Authentication in our application it works fine but when i click on back button of phone then blank page is getting displayed. Instead I want app to be closed onclick of back button. Any pointers will be helpful.,
public class FingerprintLoginActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BiometricPrompt biometricPrompt = new BiometricPrompt(this, Executors.newSingleThreadExecutor(), new BiometricPrompt.AuthenticationCallback() {
#Override
public void onAuthenticationError(int errorCode, #NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
if (errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
// user clicked negative button
} else {
// TODO: Called when an unrecoverable error has been encountered and the operation is complete.
}
}
#Override
public void onAuthenticationSucceeded(#NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
//TODO: Called when a biometric is recognized.
Context.Fingerprint = true;
Intent fingerprintIntent = new Intent(FingerprintLoginActivity.this, MainActivity.class);
fingerprintIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(fingerprintIntent);
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
//TODO: Called when a biometric is valid but not recognized.
}
});
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("touch to fingerprint scanner")
.setNegativeButtonText("Cancel")
.build();
biometricPrompt.authenticate(promptInfo);
}
}
I implement based on the instructions given here and here. The back button works fine for me: the dialog/prompt simply closes and I'm back to the Activity. Do you recognize the blank page you are seeing? perhaps you are implementing the API in a blank Activity? Try following the blog posts mentioned above and let us know how it goes.
UPDATE: based on your edit
Since you want to exit the Activity when the user clicks the back button, you have to handle BiometricPrompt.ERROR_USER_CANCELED in your code by calling finish():
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
Log.d(TAG, "onAuthenticationError -> $errorCode :: $errString")
if (errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
loginWithPassword()
}else if(errorCode == BiometricPrompt.ERROR_USER_CANCELED){
finish()
}
}
For dismiss the Fingerprint dialog, you must call to:
biometricPrompt.cancelAuthentication()

Android Acitivity Life Cycle Handling error

Good Day, So I have this program where the user will scan a QR code and get the value of it in the SQLite database but before I get the value the dialog box pops-up messaging me that "there is no participant found". Below is my code:
This is my onStart override.
#Override
protected void onStart()
{
super.onStart();
getparticipantid = tvParticipantID.getText().toString();
etparticipantidvalue.setText(getparticipantid);
getParticipantIbeam();
}
This is my activity where it will load the data from the database once the user scans the QR code.
private void getParticipantIbeam()
{
SQLiteFunctionUlitity.GameIBeamParticipant memberInfo = SQLiteFunctionUlitity.getparticipantIbeam(getparticipantid, mDbHelper.getSqliteObjectWithReadable());
if (memberInfo != null)
{
tvParticipantName.setText(memberInfo.getParticipantName());
tvParticipantNation.setText(memberInfo.getParticipant_nationality());
tvParticipantCategory.setText(memberInfo.getCategory());
tvWave.setText(memberInfo.getWave_number());
tvCategory.setText(memberInfo.getCategory());
}
else
{
Context context = this;
AlertDialog.Builder builder1 = new AlertDialog.Builder(context);
builder1.setMessage("No Participant found in the Game.");
builder1.setCancelable(true);
builder1.setPositiveButton("Scan Again", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
Intent intent = new Intent(GameiBeamLineTracing.this, ScanGameIbeam.class);
startActivity(intent);
finish();
}
});
builder1.setNegativeButton("Close", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
onStop();
}
});
AlertDialog alert11 = builder1.create();
alert11.show();
}
}
As you can see I call the getParticipantIbeam activity in onStart method but when I call it, it reads the else statement rather than the if statement.
I know this is a simple if else statement and lifecycle but I am desperate to know the answer.
I have used the library for scanning QR code, its very simple it may help you.
QR Code implementation library for android, Click here (blikoon)
Definitely this library will solve your all QR Code related issue and dont forget to implement run time permissions like photo , gallery etc.

FlashLight App Fail to connect to camera service

Here Is my Code:
I have Added a github Permission code But it still Crashes
I have done every thing but it crashes Every Time
I also have added Permission for Camera in my manifest
parameter = camera.getParameters();
}
#Override public void onPermissionDenied(PermissionDeniedResponse response) {
Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_SHORT).show();
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("App needs permission to access camera")
.setPositiveButton("Granted", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);
myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(myAppSettings);
}
}).setNegativeButton("Denied", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
}).create().show();
}
#Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token)
{[enter image description here][1]
token.continuePermissionRequest();
}
}).check();
//getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
textview = (TextView) findViewById(R.id.textView);
flashLight = (ImageButton) findViewById(R.id.flash_light);
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//askPermission(CAMERA,camera1);
flashLight.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isFlashLightOn) {
turnOnTheFlash();
} else {
turnOffTheFlash();
}
}
});
logCat:
09-30 18:59:31.698 11339-11339/inducesmile.com.androidflashlightapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: inducesmile.com.androidflashlightapp, PID: 11339
java.lang.RuntimeException: Unable to resume activity {inducesmile.com.androidflashlightapp/inducesmile.com.androidflashlightapp.MainActivity}: java.lang.RuntimeException: Fail to connect to camera service
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3506)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3546)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2795)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1073)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
Caused by: java.lang.RuntimeException: Fail to connect to camera service
at android.hardware.Camera.(Camera.java:647)
at android.hardware.Camera.open(Camera.java:510)
at inducesmile.com.androidflashlightapp.MainActivity.turnOffTheFlash(MainActivity.java:105)
at inducesmile.com.androidflashlightapp.MainActivity.onResume(MainActivity.java:165)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
at android.app.Activity.performResume(Activity.java:6791)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3477)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3546) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2795) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
at android.os.Handler.dispatchMessage(Handler.java:110) 
at android.os.Looper.loop(Looper.java:203) 
at android.app.ActivityThread.main(ActivityThread.java:6251) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1073) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934) 
09-30 18:59:31.804 11339-11347/inducesmile.com.androidflashlightapp I/art: Enter while loop.
I also had created a flashlight sensor based app a few months back. I have created gist for the code of the flashlight activity (both java and xml) and it seems to be working fine. Take a look at the below links and see if it helps:
https://gist.github.com/robillo/b27d37be3262164ee7f5532230c28c5a
https://gist.github.com/robillo/71afef65923138ed9d6011e3bd216249
Also, try doing your processing part of the activity in the if block in onCreate() like:
askForPermissions();
if(checkForPermission()){
//Do your processing here
}
The functions are:
void askForPermissions(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
getActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
}
boolean checkForPermission(){
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
It's tough to tell without seeing your turnOnTheFlash and turnOffTheFlash functions, but I'd guess that you are not properly releasing the camera at some point as shown by the documentation.

How to resolve : android.view.WindowManager$BadTokenException - is your activity running?

I have an activity with lot of Dialogs for ex Dialog_1, Dialog_2, Dialog_3, I have implemented a WebView in one of the Dialogs lets say Dialog_2. When navigate through the Dialog's, first time the Dialog_2 with the WebView opens with no problem, but second time when I navigate to Dialog_3 and come back to Dialog_2 OR Dialog_1 to Dialog_2 and touch the WebView I get an error as mentioned bellow.
I have looked at Bad token exception but it does not work still using
if (! this.isFinishing()) {
showDialog(DIALOG_ADD_A_PERSON_BODY_MAP)
}
FATAL EXCEPTION: main
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W#41ec0fc8 is not valid; is your activity running?
FATAL EXCEPTION: main
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W#41ec0fc8 is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:806)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:265)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:73)
at android.widget.ZoomButtonsController.setVisible(ZoomButtonsController.java:373)
at android.webkit.ZoomControlEmbedded.show(ZoomControlEmbedded.java:41)
at android.webkit.ZoomManager.invokeZoomPicker(ZoomManager.java:1728)
at android.webkit.WebViewClassic.startDrag(WebViewClassic.java:11645)
at android.webkit.WebViewClassic.handleTouchEventCommon(WebViewClassic.java:11170)
at android.webkit.WebViewClassic.onHandleUiTouchEvent(WebViewClassic.java:3225)
at android.webkit.WebViewClassic.onHandleUiEvent(WebViewClassic.java:3135)
at android.webkit.WebViewClassic.access$12000(WebViewClassic.java:278)
at android.webkit.WebViewClassic$PrivateHandler.dispatchUiEvent(WebViewClassic.java:13405)
at android.webkit.WebViewInputDispatcher.dispatchUiEvent(WebViewInputDispatcher.java:1078)
at android.webkit.WebViewInputDispatcher.dispatchUiEvents(WebViewInputDispatcher.java:1066)
at android.webkit.WebViewInputDispatcher.access$300(WebViewInputDispatcher.java:78)
at android.webkit.WebViewInputDispatcher$UiHandler.handleMessage(WebViewInputDispatcher.java:1392)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5365)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
The Dialog code is
case DIALOG_ADD_A_PERSON_BODY_MAP:
try {
LayoutInflater inflaterBodyMap = this
.getLayoutInflater();
final View inflatorBodyMap = inflaterBodyMap
.inflate(
R.layout.dialog_incident_window_body_map,
null);
bodyMapWebView = (WebView) inflatorBodyMap.findViewById(R.id.webView);
bodyMapWebView.getSettings().setJavaScriptEnabled(true);
//bodyMapWebView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
//bodyMapWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
bodyMapWebView.getSettings().setBuiltInZoomControls(true);
bodyMapWebView.getSettings().setSupportZoom(true);
bodyMapWebView.loadUrl("https://www.google.co.uk");
bodyMapWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
builder.setTitle("Injured person");
builder.setView(inflatorBodyMap);
builder.setPositiveButton("Next",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
showDialog(DIALOG_ADD_A_PERSON_WAS_THE_PERSON_INJURED_ET);
wasThePersonInjured.setText(map_incident_addAPerson.get("InjuredNotes"));
}
});
builder.setNegativeButton("Back",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
showDialog(DIALOG_ADD_A_PERSON_WAS_THE_PERSON_INJURED);
}
});
return builder.create();
} catch (Exception e) {
e.printStackTrace();
}
How do I resolve this error. Your help and suggestions much appreciated.
This happens if your Activity has been killed due to some reason and window token of your activity has expired but you try and access it anyways. So to solve this put this in onPause:
#Override
protected void onPause() {
super.onPause();
if ((progress != null) && progress.isShowing()) {
progress.dismiss();
}
progress = null;
}

Error : BinderProxy#45d459c0 is not valid; is your activity running?

What is this error... i haven't found any discussion on this error in the stackoverflow community Detailed :-
10-18 23:53:11.613: ERROR/AndroidRuntime(3197): Uncaught handler: thread main exiting due to uncaught exception
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy#45d459c0 is not valid; is your activity running?
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.ViewRoot.setView(ViewRoot.java:468)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.Window$LocalWindowManager.addView(Window.java:424)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.app.Dialog.show(Dialog.java:239)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at com.vishal.contacte.Locationlistener$MyLocationListener.onLocationChanged(Locationlistener.java:86)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:179)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:112)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:128)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.os.Handler.dispatchMessage(Handler.java:99)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.os.Looper.loop(Looper.java:123)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.app.ActivityThread.main(ActivityThread.java:4363)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at java.lang.reflect.Method.invokeNative(Native Method)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at java.lang.reflect.Method.invoke(Method.java:521)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at dalvik.system.NativeStart.main(Native Method)
This is most likely happening because you are trying to show a dialog after execution of a background thread, while the Activity is being destroyed.
I was seeing this error reported once in a while from some of my apps when the activity calling the dialog was finishing for some reason or another when it tried to show a dialog. Here's what solved it for me:
if(!((Activity) context).isFinishing())
{
//show dialog
}
I've been using this to work around the issue on older versions of Android for several years now, and haven't seen the crash since.
2021 Update
It's been noted in some of the comments that it's bad to blindly cast Context to an Activity. I agree!
When I'm writing similar code these days in a Fragment (8+ years after the original answer was provided), I do it more like this:
if (!requireActivity().isFinishing) {
// show dialog
}
The main takeaway is that trying to show a dialog or update any UI after the hosting Activity has been killed will result in a crash. Do what you can to prevent that by killing your background threads when your Activity is killed, or at a minimum, use the answer here to stop your app from crashing.
I faced the same problem and used the code proposed by DiscDev above with minor changes as follows:
if (!MainActivity.this.isFinishing()){
alertDialog.show();
}
if dialog is trowing this problem because of the thread you should do run this on UI thread like that :-
runOnUiThread(new Runnable() {
#Override
public void run() {
dialog.show();
}
});
This error occurs when you are showing the dialog for a context that no longer exists.
Before calling .show() check that activity/context is not finishing
if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
alert.show();
}
I encountered this error when I had a countDownTimer in my app. It had a method calling GameOver in my app as
public void onFinish() {
GameOver();
}
but actually the game could be over before the time was up due to a wrong click of the user (it was a clicking game). So when I was looking at the Game Over dialog after e.g. 20 seconds, I forgot to cancel the countDownTimer so once the time was up, the dialog appeared again. Or crashed with the above error for some reason.
The fix to this is pretty simple. Just test if the Activity is going through its finishing phase before displaying the Dialog:
private Handler myHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DISPLAY_DLG:
if (!isFinishing()) {
showDialog(MY_DIALOG);
}
break;
}
}
};
see more here
In my case, the problem was that Context was kept as a weak reference in the class that extends Handler. Then I was passing Messenger, that wraps the handler, through an Intent to a Service. I was doing this each time the activity appeared on screen in onResume() method.
So as you understand, Messenger was serialized together with its fields (including context), because it is the only way to pass objects using Intent - to serialize them. At that moment when Messenger was passed to the service, the activity itself still wasn't ready for showing dialogs as it is in another state (being said onResume(), that is absolutely different from when the activity is already on the screen). So when messenger was deserialized, the context still was at the resuming state, while the activity actually was already on the screen. Moreover, deserialization allocates memory for new object, that is completely different from the original one.
The solution is just to bind to the service each time you need it and return a binder that has a method like 'setMessenger(Messenger messenger)' and call it, when you are binded to the service.
I solve this problem by using WeakReference<Activity> as a context. The crash never appeared again. Here is a sample code in Kotlin:
Dialog manager class:
class DialogManager {
fun showAlertDialog(weakActivity: WeakReference<Activity>) {
val wActivity = weakActivity.get()
wActivity?.let {
val builder = AlertDialog.Builder(wActivity, R.style.MyDialogTheme)
val inflater = wActivity.layoutInflater
val dialogView = inflater.inflate(R.layout.alert_dialog_info, null)
builder.setView(dialogView)
// Set your dialog properties here. E.g. builder.setTitle("MyTitle")
builder.create().show()
}
}
}
And you show the dialog like this:
val dialogManager = DialogManager()
dialogManager.showAlertDialog(WeakReference<Activity>(this#MainActivity))
If you want to be super-duper protected from crashes. Instead of builder.create().show() use:
val dialog = builder.create()
safeShow(weakActivity, dialog)
This is the safeShow method:
private fun safeShow(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
val wActivity = weakActivity.get()
if (null != dialog && null != wActivity) {
// Api >=17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (!dialog.isShowing && !(wActivity).isFinishing && !wActivity.isDestroyed) {
try {
dialog.show()
} catch (e: Exception) {
//Log exception
}
}
} else {
// Api < 17. Unfortunately cannot check for isDestroyed()
if (!dialog.isShowing && !(wActivity).isFinishing) {
try {
dialog.show()
} catch (e: Exception) {
//Log exception
}
}
}
}
}
This is a similar method that you could use for safe dismissing the dialog:
private fun safeDismissAlertDialog(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
val wActivity = weakActivity.get()
if (null != dialog && null != wActivity) {
// Api >=17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (dialog.isShowing && !wActivity.isFinishing && !wActivity.isDestroyed) {
try {
dialog.dismiss()
} catch (e: Exception) {
//Log exception
}
}
} else {
// Api < 17. Unfortunately cannot check for isDestroyed()
if (!dialog.isShowing && !(wActivity).isFinishing) {
try {
dialog.dismiss()
} catch (e: Exception) {
//Log exception
}
}
}
}
}
In Kotlin
if (!(context is Activity && context.isFinishing)) {
pausingDialog!!.show()
}
how about makes a new Instance of that dialog you want to call? I've actually just met the same problem, and that is what I do. so rather than :
if(!((Activity) context).isFinishing())
{
//show dialog
}
how about this?
YourDialog mDialog = new YourDialog();
mDialog1.show(((AppCompatActivity) mContext).getSupportFragmentManager(), "OrderbookDialog");
}
so rather than just checking is it safe or not to show the dialog, I think it's much more safe if we just create a new instance to show the dialog.
Like me, In my case I tried to create one instance (from a Fragment onCreate) and call the instance of those dialog in another content of adapterList and this will result in "is your activity running"- error. I thought that was because I just create one instance (from onCreate) and then it is get destroyed, so when I tried to call it from another adapterList I calling the dialog from old instance.
I am not sure if my solution is memory friendly or not, because I haven't tried to profile it, but it works
(well surely, it is safe if you do not create too many instance)

Categories

Resources