Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show dialog alert from a non-activity class in android

I want to show an Alert Dialog via AlertDialogManager class to a non-activity class DeviceAdminReceiverSample's method onDisabled, but whenever I call alertDialog via that method it generates error with following text

Error

06-12 12:01:19.923: E/AndroidRuntime(468): FATAL EXCEPTION: main
06-12 12:01:19.923: E/AndroidRuntime(468): java.lang.RuntimeException: Unable to start           
receiver com.android.remotewipedata.DeviceAdminReceiverSample:   
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not   
for an application

I know the issue is with context thing but I don't know what to put there so that it work, I tried this, getApplicationContext() but all vain. My code for both classes is below

AlertDialogManager

public class AlertDialogManager {

public void showAlertDialog(Context context, String title, String message,
        Boolean status) {
    final AlertDialog alertDialog = new AlertDialog.Builder(context).create();
    alertDialog.setTitle(title);
    alertDialog.setMessage(message);

    if (status != null)
        alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                alertDialog.dismiss();
            }
        });
    alertDialog.show();
}

}

DeviceAdminReceiverSample

public class DeviceAdminReceiverSample extends DeviceAdminReceiver {
static final String TAG = "DeviceAdminReceiver";
AlertDialogManager alert = new AlertDialogManager();

/** Called when this application is no longer the device administrator. */
@Override
public void onDisabled(Context context, Intent intent) {
    super.onDisabled(context, intent);
    Toast.makeText(context, R.string.device_admin_disabled,
            Toast.LENGTH_LONG).show();
    // intent.putExtra("dialogMessage", "Device admin has been disabled");
    // intent.setClass(context, DialogActivity.class);
    // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // context.startActivity(intent);
    alert.showAlertDialog(context, "Alert",
            "Device admin has been disabled", true);
}
like image 789
Saqib Avatar asked Jun 12 '13 07:06

Saqib


People also ask

How do I display a dialog in android without an activity context?

Dialog is built by ui context. The approach to show dialog without ui context (activity) in some case: call dialog in rest api, show dialog after own activity finish, call dialog in first activity and want to show it in the next activity also.

What is the difference between an alert and an alert dialog?

AlertDialog is a lightweight version of a Dialog. This is supposed to deal with INFORMATIVE matters only, That's the reason why complex interactions with the user are limited. Dialog on the other hand is able to do even more complex things .


2 Answers

Just add this before your alertDialog.show();

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

or try following if above didn't work:

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL); 

and use this permission:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
like image 118
Eliran Kuta Avatar answered Sep 21 '22 08:09

Eliran Kuta


If you always want to get the current activity from anywhere in the app you can register an ActivityLifecycleCallback on your Application instance.

Here's an untested implementation that might get you closer.

public class TestApp extends Application {

    private WeakReference<Activity> mActivity = null;

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                mActivity = new WeakReference<Activity>(activity);
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                mActivity.clear();
            }

            /** Unused implementation **/
            @Override
            public void onActivityStarted(Activity activity) {}

            @Override
            public void onActivityResumed(Activity activity) {}
            @Override
            public void onActivityPaused(Activity activity) {}

            @Override
            public void onActivityStopped(Activity activity) {}

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
        });
    }

    public Activity getCurrentActivity() {
        return mActivity.get();
    }

}

Then to use this throughout your app you would do some call like this ...

Activity activity = ((TestApp)getApplicationContext()).getCurrentActivity(); 

The advantages are you can always keep track of your current activity, however its a little too overkill for just handling Dialogs from within the Activity.

like image 45
Chris Sullivan Avatar answered Sep 19 '22 08:09

Chris Sullivan