从服务显示警报对话框时获取异常 - 无法添加窗口 - 令牌null不适用于应用程序

时间:2013-10-30 08:52:43

标签: android android-service

从服务显示警报对话框时获取异常。

以下是我的Service类中的代码:我正在尝试显示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();
            }

enter image description here

5 个答案:

答案 0 :(得分:21)

我有这个问题,但现在是solved,如果您希望真的从服务运行alertDialog,您应该将对话框配置为系统警报并记住在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();

答案 1 :(得分:4)

创建你的gui时,你应该记住一些事情:

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

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

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

    1. 您可以使用runOnUiThread在UI线程中运行一段代码。
    2. 您可以使用messageHandler。
    3. 您可以使用广播发送方和接收方。
    4. 我认为对于你的情况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);
      

      我希望这可以帮到你。

答案 2 :(得分: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();
}

答案 3 :(得分:1)

试试这个。

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

编辑。

很抱歉没有评论。将启动服务的Context放在服务中并使用它。

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

        this.myContext= myContext;
     }

   public void showDialog()
   {
        AlertDialog d = new AlertDialog.Builder(myContext);
   }
}

答案 4 :(得分:0)

您可以执行UI内容,例如仅在UI线程中显示AlertDialog。 由于您的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();
            }

            });
}