36

Good day, I am trying to show an alert dialog after a system reboot in a broadcast receiver. I have added the receiver in my manifest and called the required permission, but am getting an error in showing the dialog. Please How can i implement this correctly?.. Thank you

my code:

public void onReceive(final Context context, Intent intent) {
    Log.d(TAG, "received boot completed broadcast receiver... starting settings");


    String settings = context.getResources().getString(R.string.restart_setting);
        String yes = context.getResources().getString(R.string.Settings);
        String no = context.getResources().getString(R.string.Cancel);

              final AlertDialog.Builder builder = new AlertDialog.Builder(context);
                builder.setMessage(settings)
                       .setCancelable(false)
                       .setPositiveButton(yes, new DialogInterface.OnClickListener() {
    public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) 
   Intent config = new Intent(context, WeatherConfigure.class)
     context.startActivity(config);

    }
 })
    .setNegativeButton(no, new DialogInterface.OnClickListener() {
        public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
             dialog.cancel();
        }
    });
  final AlertDialog alert = builder.create();
  alert.show();

    }

am getting this log error:

01-07 01:42:01.559: ERROR/AndroidRuntime(2004): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application

01-07 01:42:01.559: ERROR/AndroidRuntime(2004): at android.view.ViewRoot.setView(ViewRoot.java:548)

01-07 01:42:01.559: ERROR/AndroidRuntime(2004):at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)

01-07 01:42:01.559: ERROR/AndroidRuntime(2004): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)

01-07 01:42:01.559: ERROR/AndroidRuntime(2004):at android.app.Dialog.show(Dialog.java:288)

01-07 01:42:01.559: ERROR/AndroidRuntime(2004):at com.MuaaApps.MyWeatherUpdate.myWeatherBroadcastReceiver.onReceive(MyWeatherBroadcastReceiver.java:59)

01-07 01:42:01.559: ERROR/AndroidRuntime(2004): at android.app.ActivityThread.handleReceiver(ActivityThread.java:1994)
irobotxx
  • 5,963
  • 11
  • 62
  • 91
  • A Toast message or a Notification might be more appropriate in this case, rather than blasting the user with an alert dialog as their phone turns on. – cottonBallPaws Jan 07 '12 at 02:56
  • @littleFluffyKitty, yeah i understand what you mean. am just trying different scenarios to see which i think will give a good user experience, but i must admit the notification suggestion you made is a very attractive option. did not think of that. Thanks – irobotxx Jan 07 '12 at 08:48

7 Answers7

51

The problem is you are trying to show an AlertDialog from a BroadcastReceiver, which isn't allowed. You can't show an AlertDialog from a BroadcastReceiver. Only activities can display dialogs.

You should do something else, have the BroadcastReceiver start on boot as you do and start an activity to show the dialog.

Here is a blog post more on this.

EDIT:

Here is how I would recommend doing it. From your BroadcastReceiver start an Activity with an AlertDialog as such..

public class NotifySMSReceived extends Activity 
{
    private static final String LOG_TAG = "SMSReceiver";
    public static final int NOTIFICATION_ID_RECEIVED = 0x1221;
    static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        IntentFilter filter = new IntentFilter(ACTION);
        this.registerReceiver(mReceivedSMSReceiver, filter);
    }

    private void displayAlert()
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Are you sure you want to exit?").setCancelable(
            false).setPositiveButton("Yes",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            }).setNegativeButton("No",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
        AlertDialog alert = builder.create();
        alert.show();
    }

    private final BroadcastReceiver mReceivedSMSReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (ACTION.equals(action)) 
            {
                //your SMS processing code
                displayAlert();
            }
        }
    }
}

As you see here I NEVER called setContentView(). This is because the activity will have a transparent view and only the alert dialog will show.

Claudio
  • 2,191
  • 24
  • 49
coder_For_Life22
  • 26,645
  • 20
  • 86
  • 118
29

You can't use dialog on BroadcastReceiver, so instead you better call an activity for the dialog box from the BroadcastReceiver,

add this code in your onReceive function :

@Override
public void onReceive(Context context, Intent intent) 
{
    Intent i = new Intent(context, {CLASSNAME}.class); 
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    context.startActivity(i);
}

fill the {CLASSNAME} with the dialog activity, heres my dialog activity :

package com.example.mbanking;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;


// ALERT DIALOG
// Sources : http://techblogon.com/alert-dialog-with-edittext-in-android-example-with-source-code/

public class AlertDialogActivity extends Activity 
{

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder
        .setTitle("Test")
        .setMessage("Are you sure you want to exit?")
        .setCancelable(false)
        .setPositiveButton("Yes", new DialogInterface.OnClickListener() 
        {
            public void onClick(DialogInterface dialog, int id) 
            {
                dialog.cancel();
            }
        })
        .setNegativeButton("No", new DialogInterface.OnClickListener() 
        {
            public void onClick(DialogInterface dialog, int id) 
            {
                dialog.cancel();
            }
        });
    AlertDialog alert = builder.create();
    alert.show();
}
}

where I got the answer ?, here : How do you use an alert dialog box in a broadcast receiver in android? thanks to Femi !!, I just spread the news :D

Community
  • 1
  • 1
Bhimbim
  • 1,348
  • 2
  • 19
  • 15
7

Here is a post on how to do it. You can get the source code from here.

You can't show dialog directly from your broadcast receiver. You have to use an Activity. Also, in order to receive ACTION_BOOT_COMPLETED your activity must be first explicitly started by user or by another application (google application stopped state for more information).

Basically, to achieve the required functionality, you need to do:

  1. Create transparent activity that shows dialog.
  2. Create BroadcastReceiver that receives ACTION_BOOT_COMPLETED and starts your activity.
  3. Register your broadcast receiver in the manifest and acquire a proper permission.

Also, this question provides more information on how to create a transparent activity.

Community
  • 1
  • 1
Nikolai Samteladze
  • 7,699
  • 6
  • 44
  • 70
  • Its a great post.Thanks but i want to show the dialog after triggering the receiver from command prompt.How to achieve that, here the dialog is showing at first. – AndroidOptimist Dec 18 '13 at 06:27
  • As I understand, you goal is still to show dialog from `BroadcastReceiver`. The only difference is that your receiver is triggered by another intent (not `android.intent.action.BOOT_COMPLETED`), right? – Nikolai Samteladze Dec 18 '13 at 13:37
  • I think you can just change `` attribute in your `BroadcastReceiver`'s `` to point to the intent you need. – Nikolai Samteladze Dec 30 '13 at 22:30
7

The best way is to make an activity and set its "Theme" attribute to "Theme.Translucen"

 <activity
        android:name=".MyAlertDialog"
        android:label="@string/title_activity_alert_dialog"
        android:launchMode="singleInstance"
        android:theme="@android:style/Theme.Translucent" >
    </activity>

and in your activity create an Alert dialog:

public class MyAlertDialog extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE); //hide activity title
    setContentView(R.layout.activity_my_alert_dialog);

    AlertDialog.Builder Builder=new AlertDialog.Builder(this)
            .setMessage("Do You Want continue ?")
            .setTitle("exit")
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setNegativeButton(R.string.No, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    MyAlertDialog.this.finish();
                }
            })
            .setPositiveButton(R.string.Yes,null);
    AlertDialog alertDialog=Builder.create();
    alertDialog.show();

}

}

and in brodcastreciver:

 @Override
public void onReceive(Context context, Intent intent) {

    Intent i=new Intent(context.getApplicationContext(),MyAlertDialog.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(i);

}
}
hadi seylani
  • 117
  • 1
  • 7
4

This may be old and answered thread, but the answered answer wasnt helpful at all.

You cannot launch a popup dialog in your implementation of onReceive(). BroadcastReceiver

Instead of dialogs or popupWindow, you can use an activity which is themed as dialog

 <activity 
   android:taskAffinity=""
   android:name=".activity.CallActivity"
   android:label="@string/app_name"
   android:theme="@style/AppTheme.Dialog" />

Please notice that I add taskAffinity inside of the block(AndroidManifest.xml)

Then you can just use it as regular activities.

Intent intentPhoneCall = new Intent(context, CallActivity.class);
intentPhoneCall.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentPhoneCall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentPhoneCall);

Hope it helps. Happy codings.

ralphgabb
  • 10,298
  • 3
  • 47
  • 56
  • This worked very well for me as well. Thanks! We ended up using our own existing Dialog theme and it was great. Colors and Backgrounds were correct, the Activity background was transparent and the animation was a Fade instead of a typical slide or something that you see with starting new Activities. – Joshua Pinter Feb 18 '20 at 15:55
1
  1. Display a Dialog from Broadcast Receiver is not possible.
  2. we should show the Dialog from Activity only.
  3. But your application context having only Broadcast Receiver, then we should launch the activity as "FLAG_ACTIVITY_NEW_TASK", then it creates the stack.
  4. If we Launch the activity with this flag "FLAG_ACTIVITY_NEW_TASK" we can't remove from the stack.

  5. So after closing the application, then we are trying to start the application from the stack, it shows the same Activity, because this activity having the flag "FLAG_ACTIVITY_NEW_TASK", so it should not create the new instance and use the existing instance.

But we want show the dialog only once. for this we need to handle programmatic ally.

 if (count == 0) {
            mBuilder = new Dialog(this);
            mMsg = getIntent().getStringExtra(AlarmSchedulerUtils.EXTRA_MSG);
            Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
            mRingTome = RingtoneManager.getRingtone(ReminderDialog.this, notification);
            mRingTome.play();
            count++;
            showReminderDialog();
        } else {
            Intent intent=new Intent(ReminderDialog.this,SplashActivity.class);
            startActivity(intent);
            finish();
        }

This is worked for me.

Kona Suresh
  • 1,836
  • 1
  • 15
  • 25
-1

in on onReceive while calling the intent u just need to put it in a handler with delay of 400ms by the way for me it woked like charm

@Override
public void onReceive(Context context, Intent intent) 
{
      new Handler().postDelayed(new Runnable() {
                   @Override
                    public void run() {
        
                        Intent i = new Intent(context, {CLASSNAME}.class); 
                        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
                        context.startActivity(i);
                   }
               }, 400);
}
yash gupta
  • 47
  • 1
  • 7