2013-10-30 41 views
6

從服務顯示警報對話時獲取異常。從服務顯示警報對話時獲取異常 - 無法添加窗口 - 令牌null不適用於應用程序

以下是我的服務類中的代碼:我試圖顯示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

+1

你無法控制的服務界面,你能做的最好的事情是開始一個新的活動,使它看起來像一個對話框。乾杯! – user2652394

+0

@ user2652394這是否必須是一個活動,或者它可以只是一個XML佈局? –

+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

看起來您對builder.setTitle()有一個額外的close paren,對於builder.setPositiveButton.onClick()缺少一個閉合括號。 – jakeneff

+0

thnx @jakeneff,現在已更正 –

+0

如何將對話框配置爲System Alert? –

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

      }); 
} 
+0

runOnUiThread此方法在Activity中。但我的服務不會擴展活動。那我該如何處理呢? –

+0

frm從哪裏開始你的服務..從接收器? – bakriOnFire

4

你應該保留一些東西在你的心中,同時創造你的GUI:

  1. 所有耗時非GUI工作應該是在後臺完成(使用asyncTask,服務,線程等)。

  2. 應始終從UIthread創建和更新GUI(如視圖和其他圖形對象)。

所以創建和顯示對話框是一個UI工作,所以它應該在UI線程中。要在UI線程中運行任何代碼,您可以使用不同的方法,例如:

  1. 您可以使用runOnUiThread在UI線程中運行一段代碼。
  2. 您可以使用messageHandler。
  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); 

我希望這可以幫助你。

+1

runOnUiThread此方法在Activity中。但我的服務不會擴展活動。那我該如何處理呢? –

+1

真實情況是,您無法在非ui線程中創建您的ui,因此您需要將廣播從您的服務發送到您的活動,並且您可以創建對話。 –

+1

這個答案是不正確的。通常所說的「UI線程」實際上只是應用程序的主線程。除非您啓動自己的線程,或者您正在使用IntentService,否則您的服務和活動都將在主線程中運行。您也可以通過直接訪問WindowManager直接從服務生成UI。這裏的實際限制是您需要設置對話框的窗口類型以便從服務中顯示它。 Ziprox09給出了正確的答案。 – simonp

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); 
    } 
} 
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(); 
} 
相關問題