来自Android服务的警报对话框

31

我如何在服务中显示对话框?


https://stackoverflow.com/a/29804684/2149195 - RBK
7个回答

28

不使用活动的另一种方法:

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" />

3
我只需要一个快速的方法,在启动服务进行调试后选择某些东西,这正是我所寻找的。 - Fabian N.
3
TYPE_SYSTEM_ALERT已被弃用,请使用TYPE_APPLICATION_OVERLAY。https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_SYSTEM_ALERT - humble_wolf

27

android-smspopup可以实现这个功能。

当服务接收到短信时,它会启动一个Activity

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

编辑:对话框活动是使用此代码在此处启动的。

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

以下是 getPopupIntent() 的声明(代码在此处):

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 类显然定义了对话框活动。它在 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>

谢谢,我已经搜索了几个小时并尝试了新的方法。感谢,它起作用了。 - sajad abbasi

22

来自服务的Material样式对话框

通过一个服务,你可以轻松地展示一个Material Design样式的对话框,同时操纵其窗口类型、属性和LayoutParams。

开始之前:AppCompat库

本指南假定你正在使用 Android AppCompat 库。

开始之前:权限

此方法需要SYSTEM_ALERT_WINDOW权限。通常想要显示对话框的服务还会将一些视图绘制在系统界面上(使用WindowManager.addView()方法添加),因此你可能已经在清单文件中声明了该权限的使用。如果没有,请添加以下代码:

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

Android 6.0 Marshmallow中,用户必须明确允许您的应用程序“绘制在其他应用程序上方”。 您可以以编程方式启动包含开关的系统设置Activity:

@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;
    }
}

创建自定义的Material Design对话框主题

themes.xml文件中创建此主题,并使用您的应用程序颜色进行自定义:

<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>

启动您的对话框

在您的服务内部:

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();

什么是 RC_OVERLAY - avi
@avi 这是一个请求代码整数。你可以选择任何数字,并将其设置为常量! - araks
@araks 谢谢,太好了。你只需要在“dialog.show()”后面设置“lp”。 - Lord Sepid

5

文档建议您应该使用通知。重新评估为什么您需要使用对话框。您想要实现什么目标?


29
也许需要一个闹钟?有时弹出窗口是有原因的! - james

2
首先,您需要将Activity转化为Service, 所以在您的Activity中添加:
public static Activity mactivity;

在 On create 中添加以下内容:
mactivity = YourActivity.this;

并且当我们转移到您的服务时,还要声明以下内容:
YourActivity mact;
YourActivity act;

在创建服务时,这是我们的转换。
mact = (YourActivity) act.mactivity;

而警告对话框将会如下所示:

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
            }
        });

请记住,在 Alert Builder 中使用的 Cast 类是 mact... 对我来说这很有效,希望它能帮到你。

2

当我需要显示对话框时,我会在服务内调用下面的代码。

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();
}

请确保在清单文件中添加以下权限:android.permission.SYSTEM_ALERT_WINDOW。

我认为对于SDK 23及以上的版本,用户应该在应用程序管理器中明确设置“在其他应用程序上绘制”权限,以便启动此服务的应用程序能够使用它。


0

这里有一个更详细的解释,如何使用半透明Activity从服务中显示AlertDialog,以及如何避免一些问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接