Alert dialog from Android service

2019-01-03 16:40发布

How do I display dialog from a service?

7条回答
小情绪 Triste *
2楼-- · 2019-01-03 17:13

Material styled Dialog from a Service

From a Service, you can easily show a Material Design styled Dialog manipulating its Window type, attributes and LayoutParams.

Before we begin: AppCompat Library

This guide presumes you are using Android AppCompat libray.

Before we begin: Permissions

This method needs the SYSTEM_ALERT_WINDOW permission. Usually a Service that wants to display a Dialog also has some Views drawn over the system UI (added using WindowManager.addView() method) so you might have already declared this permission usage inside you manifest. If not, add this line:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

In Android 6.0 Marshmallow, the user must explicitly allow your app to "draw over other apps". You can programmatically start the system settings Activity that contains the switch:

@Override
protected void onResume() {
    super.onResume();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
        openOverlaySettings();
    }
}

@TargetApi(Build.VERSION_CODES.M)
private void openOverlaySettings() {
    final Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                                     Uri.parse("package:" + getPackageName()));
    try {
        startActivityForResult(intent, RC_OVERLAY);
    } catch (ActivityNotFoundException e) {
        Log.e(TAG, e.getMessage());
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case RC_OVERLAY:
            final boolean overlayEnabled = Settings.canDrawOverlays(this);
            // Do something...
            break;
    }
}

Create your custom Material Design Dialog theme

Inside themes.xml create this theme and customize it with your app colors:

<style name="AppTheme.MaterialDialogTheme" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorPrimary">@color/brand_primary</item>
    <item name="colorPrimaryDark">@color/brand_primary_dark</item>
    <item name="colorAccent">@color/brand_accent</item>

    <item name="android:windowBackground">@drawable/dialog_background_light</item>

    <item name="android:textColorPrimary">@color/primary_text_light</item>
    <item name="android:textColorSecondary">@color/secondary_text_light</item>
    <item name="android:textColorTertiary">@color/secondary_text_light</item>
</style>

Launch your Dialog

Inside your Service:

final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this, R.style.AppTheme_MaterialDialogTheme);

dialogBuilder.setTitle(R.string.dialog_title);
dialogBuilder.setMessage(R.string.dialog_message);
dialogBuilder.setNegativeButton(R.string.btn_back,
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        }
);

final AlertDialog dialog = dialogBuilder.create();
final Window dialogWindow = dialog.getWindow();
final WindowManager.LayoutParams dialogWindowAttributes = dialogWindow.getAttributes();

// Set fixed width (280dp) and WRAP_CONTENT height
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialogWindowAttributes);
lp.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 280, getResources().getDisplayMetrics());
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
dialogWindow.setAttributes(lp);

// Set to TYPE_SYSTEM_ALERT so that the Service can display it
dialogWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialogWindowAttributes.windowAnimations = R.style.DialogAnimation;
dialog.show();
查看更多
老娘就宠你
3楼-- · 2019-01-03 17:15

firstable you need to cast your Activity in Service so in your Activity add

public static Activity mactivity;

and in On create add this

mactivity = YourActivity.this;

and when we move to your Service alse declare this :

YourActivity mact;
YourActivity act;

and in on Create service this is our casting

mact = (YourActivity) act.mactivity;

and the alert dialog will be look like this :

AlertDialog.Builder builder = new AlertDialog.Builder(mact);
        builder.setMessage(getResources().getString(R.string.string));
        builder.setIcon(R.drawable.chat);
        builder.setTitle(R.string.app_name);
        builder.setPositiveButton(getResources().getString(R.string.Ok), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                // TODO Auto-generated method stub
               your message
            }
        });

remember that mact is the Cast class to use in Alert Builder ...that works fine for me hope it help .

查看更多
Anthone
4楼-- · 2019-01-03 17:17

The documentation suggests that you should make use of notifications. Re-evaluate why you might need to use dialogs. What are you trying to achieve?

查看更多
放我归山
5楼-- · 2019-01-03 17:19

Another way without using an activity:

AlertDialog alertDialog = new AlertDialog.Builder(this)
                    .setTitle("Title")
                    .setMessage("Are you sure?")
                    .create();

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

Please note that you have to use this permission:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
查看更多
beautiful°
6楼-- · 2019-01-03 17:22

I am calling the below, inside the service when I need to show a dialog.

public void ShowYesNoDialog() {

    DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            switch (which) {
                case DialogInterface.BUTTON_POSITIVE:
                    //Yes Button Clicked
                    break;

                case DialogInterface.BUTTON_NEGATIVE:
                    //No button clicked
                    break;
            }
        }
    };

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Did the dialog display?")
    .setPositiveButton("Yes", dialogClickListener)
    .setNegativeButton("No", dialogClickListener);
    AlertDialog alertDialog = builder.create();
    alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 
    alertDialog.show();
}

Make sure you have the below permission added to the manifest. android.permission.SYSTEM_ALERT_WINDOW

I also think that for SDK 23 and above, the user should explicitly set the "Draw over other Apps" permission from the Application manager for the App that starts this service.

查看更多
Summer. ? 凉城
7楼-- · 2019-01-03 17:29

android-smspopup does exactly that.

A service receives a sms and it starts an Activity with:

android:theme="@android:style/Theme.Dialog"

EDIT: The dialog activity is started here with this code

private void notifyMessageReceived(SmsMmsMessage message) {
    (...)
    context.startActivity(message.getPopupIntent());
    (...)
}

With getPopupIntent() declared as followed (code here):

public Intent getPopupIntent() {
    Intent popup = new Intent(context, SmsPopupActivity.class);
    popup.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    popup.putExtras(toBundle());
    return popup;
    }

SmsPopupActivity class obviously defines the dialog activity. Its declared as followed in AndroidManifest.xml:

    <activity
        android:name=".ui.SmsPopupActivity"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:launchMode="singleTask"
        android:screenOrientation="user"
        android:taskAffinity="net.everythingandroid.smspopup.popup"
        android:theme="@style/DialogTheme" >
    </activity>
查看更多
登录 后发表回答