7

显示来自服务的警报对话框时出现异常。

以下是我的服务类中的代码:我正在尝试显示一个 AlertDialog。

但我收到错误:无法添加窗口——令牌 null 不适用于应用程序

我还将我的日志快照附加到这个问题。

 if(!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)&& !mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){

                Log.d("TrackingService","H: Exception after this");

                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Your GPS seems to be disabled, do you want to enable it?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                    }
                })
                .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog,  final int id) {
                        dialog.cancel();
                    }
                });
                AlertDialog alert = builder.create();
                alert.show();
            }

在此处输入图像描述

4

5 回答 5

21

我有这个问题,但现在是solved,如果你真的想从服务中运行 alertDialog,你应该将对话框配置为System Alert并记住在你的 AndroidManifest.xml 中添加权限:

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

/这里是示例代码:

AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Test dialog");
builder.setIcon(R.drawable.icon);
builder.setMessage("Content");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        //Do something
        dialog.dismiss();
   }
});
builder.setNegativeButton("Close", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        dialog.dismiss();
    }
});
AlertDialog alert = builder.create();
alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alert.show();
于 2014-02-21T09:07:20.320 回答
4

在创建 gui 时,您应该记住一些事情:

  1. 所有耗时的非 gui 工作都应在后台完成(使用 asyncTask、Services、Threads 等)。

  2. GUI(如视图和其他图形对象)应始终从 UIthreads 创建和更新。

所以创建和显示对话框是一个 UI 工作,所以它应该在 UI 线程中。要在 UI 线程中运行任何代码,您可以使用不同的方法,例如:

  1. 您可以使用 runOnUiThread 在 UI 线程中运行一段代码。
  2. 您可以使用消息处理程序。
  3. 您可以使用广播发送方和接收方。

我认为对于你的情况 runOnUiThread 是最好的所以使用

runOnUiThread (new Runnable() {
                public void run ()
                {
                    // WRITE YOUR PIECE OF CODE HERE TO UPDATE OR CREATE GUI.
                }
            });

要理解这个概念,这可以帮助您:

http://developer.android.com/guide/components/processes-and-threads.html

要创建广播,您可以使用:

第 1 步:在您开始服务的活动中创建广播接收器。

   BroadcastReceiver receiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("create_dialog")) {
                // create your dialog here.
            }
        }
    };

第 2 步:在创建广播接收器后注册您的接收器。

IntentFilter filter = new IntentFilter("create_dialog");
registerReceiver(receiver, filter);

第 3 步:从您的服务发送广播以显示对话框。

Intent intent = new Intent("create_dialog");
intent.putExtra("dialog_data", data_object to display in dialog);
SendBroadcast(intent);

我希望这可以帮助你。

于 2013-10-30T09:08:55.123 回答
2

不要创建新的透明活动,而是使用SYSTEM_ALERT_WINDOW权限来执行此操作

public void onReceive(Context ctx, Intent intent) {
    LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View popup = inflater.inflate(R.layout.mypopup, null, false);
    CustomDialog dialog = new CustomDialog(ctx, popup );

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

    dialog.getWindow().getAttributes().windowAnimations = R.style.PauseDialogAnimation;
    dialog.show();
}
于 2014-09-29T07:54:25.010 回答
1

试试这个。

AlertDialog.Builder alertDialog  = new AlertDialog.Builder(myContext);

编辑。

抱歉没有评论。将启动您的服务的上下文像服务中的实例一样放入并使用它。

class SomeService 
{   
     private final Context myContext;
     public WebService(Context myContext) 
     {

        this.myContext= myContext;
     }

   public void showDialog()
   {
        AlertDialog d = new AlertDialog.Builder(myContext);
   }
}
于 2013-10-30T09:44:36.833 回答
0

你可以做 UI 的东西,比如AlertDialog只在 UI 线程中显示。而且由于您service没有在 UI 线程上运行,因此您会收到此异常。

尝试使用runOnUiThread显示警报:-

if(!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)&& !mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){

            runOnUiThread(new Runnable(){

            public void run(){
                Log.d("TrackingService","H: Exception after this");

                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Your GPS seems to be disabled, do you want to enable it?")
                            .setCancelable(false)
                            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog, final int id) {
                                    startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                                }
                            })
                            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog,  final int id) {
                                    dialog.cancel();
                                }
                            });
               AlertDialog alert = builder.create();
               alert.show();
            }

            });
}
于 2013-10-30T09:01:06.173 回答