2012-03-17 86 views
28

這看起來應該很簡單,但我沒有在任何地方找到答案。我有一個Android應用程序在後臺執行網絡任務。如果出現錯誤,我想顯示錯誤對話框。當任務返回時,我不知道哪個Activity在前臺。基於this post,它看起來像我們不能使用應用程序上下文來顯示對話框(事實上,如果我嘗試,我會得到崩潰)。如何在沒有Activity上下文的情況下在android中顯示對話框?

那麼如何獲取當前活動的上下文?同樣,網絡任務的接收者正在應用程序上下文中運行,而不是在特定的活動中運行。任何其他想法?

編輯:我應該澄清。如果我不是前臺應用程序,我不想顯示錯誤對話框。我只對我們的應用現在處於前臺的情況感興趣。

+0

你可以使用[吐司](http://developer.android.com/reference/android/widget/Toast.html)。 Afaik沒有辦法顯示一個對話框而不是活躍的前臺應用程序。 – zapl 2012-03-17 15:17:58

回答

20

如果錯誤回來,我要顯示一個錯誤對話框。

如果您知道用戶正在主動使用您的應用程序,請執行此操作。如果你在別的事情中打斷他們(玩遊戲,看電影,看書),用戶會非常惱火。

那麼我該如何獲取當前活動的上下文?

你不知道。您最多可以讓當前活動知道它需要做些什麼。

還有其他想法嗎?

一種可能性是使用一個有序廣播,所以如果有前景的活動,它得到控制,否則你養Notification讓用戶瞭解這一問題,而不彈出一個對話框。接收訂購廣播的活動可以顯示AlertDialog或以其他方式讓用戶瞭解該問題。我寫了關於如何做in a blog post(和a book chapter,對於這個問題)和here is a sample application這些技術的細節。或者,請致電startActivity()啓動a dialog-themed activity

+0

如果他沒有上下文,他如何創建併發布通知? Afaik通知需要創建上下文嗎?我有一個後臺線程運行,並沒有綁定到任何活動 - 因此我無法獲得一個活動上下文來首先啓動通知。 – AgentKnopf 2012-10-26 14:42:47

+0

@ Zainodis:「我有一個後臺線程運行,不綁定到任何活動」 - 這是一個錯誤。您應該讓它由某個組件(如服務)管理。然後,「服務」是您的「上下文」,用於跟蹤我在答案中寫的內容。 – CommonsWare 2012-10-26 15:39:56

+0

感謝提示 - 我們曾經爲它提供服務(後臺線程處理服務器連接) - 然後我們恢復到後臺線程,因爲偶爾我們的服務會被殺死(通過我們假設的操作系統,因爲沒有例外或類似的引起突然失敗)沒有明顯的原因(這在我們的情況是一個不行)。 – AgentKnopf 2012-10-26 21:09:48

0

在後臺正在進行什麼類型的網絡任務。我會建議可能重新考慮設計。也許通知會更好?或者可能是一個「結果總結」屏幕。作爲一個用戶,如果我沒有積極地等待任務完成,我寧願有一個非突兀的錯誤信號。

6

我創建了一個實現CommonsWare思想的幫助類。希望顯示警報的活動只需調用Alerts.register()和Alerts.unregister()。然後任何人都可以調用Alerts.displayError()。

評論歡迎。

public class Alerts { 

    private static class AlertReceiver extends BroadcastReceiver { 

     private static HashMap<Activity, AlertReceiver> registrations; 
     private Context activityContext; 

     static { 
      registrations = new HashMap<Activity, AlertReceiver>(); 
     } 

     static void register(Activity activity) { 
      AlertReceiver receiver = new AlertReceiver(activity); 
      activity.registerReceiver(receiver, new IntentFilter(MyApplication.INTENT_DISPLAYERROR)); 
      registrations.put(activity, receiver); 
     } 

     static void unregister(Activity activity) { 
      AlertReceiver receiver = registrations.get(activity); 
      if(receiver != null) { 
       activity.unregisterReceiver(receiver); 
       registrations.remove(activity); 
      } 
     } 

     private AlertReceiver(Activity activity) { 
      activityContext = activity; 
     } 

     @Override 
     public void onReceive(Context context, Intent intent) { 
      abortBroadcast(); 
      String msg = intent.getStringExtra(Intent.EXTRA_TEXT); 
      displayErrorInternal(activityContext, msg); 
     } 
    } 

    public static void register(Activity activity) { 
     AlertReceiver.register(activity); 
    } 

    public static void unregister(Activity activity) { 
     AlertReceiver.unregister(activity); 
    } 

    public static void displayError(Context context, String msg) { 
     Intent intent = new Intent(MyApplication.INTENT_DISPLAYERROR); 
     intent.putExtra(Intent.EXTRA_TEXT, msg); 
     context.sendOrderedBroadcast(intent, null); 
    } 

    private static void displayErrorInternal(Context context, String msg) { 
     AlertDialog.Builder builder = new AlertDialog.Builder(context); 
     builder.setTitle("Error") 
       .setMessage(msg) 
       .setCancelable(false) 
       .setPositiveButton("Ok", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int id) { 
         dialog.cancel(); 
        } 
       }); 
     final AlertDialog alert = builder.create(); 

     alert.show(); 
    } 

} 
+0

你好, 我如何使用這個類,我有這個問題。 什麼是MyApplication? – MRT 2013-09-09 07:47:04

+0

MyApplication。INTENT_DISPLAYERROR是一個常量,我假設的是,ManicBlowfish的應用程序代表一個字符串。你可以用你選擇的字符串替換它。 – Jon 2013-12-11 20:00:09

1

我也遇到了這個問題。我找到了一個簡單而有效的解決方案。通常,我們有一個用於處理一些常見邏輯的基本活動。所以有這個:

public class BaseActionBarActivity extends ActionBarActivity{ //this BaseActionBarActivity is the Base Act 

    private static BaseActionBarActivity current; 

    @Override 
    protected void onStart() { 
    super.onStart(); 
    current=this; 
    } 


    public static BaseActionBarActivity getCurrentContext() { 
    return current; 
    } 
} 

當前字段是當前的上下文Actitvity。我相信沒有內存泄漏問題。這對我來說很有效!希望有幫助

0

爲什麼不使用事件總線(https://github.com/greenrobot/EventBus)?

  1. 定義事件:

    public class ShowErrorMessageEvent { 
    
        public String errorMessage; 
    
        public ShowErrorMessageEvent(String errorMessage) { 
         this.errorMessage = errorMessage; 
        } 
        public String getErrorMessage() { 
         return this.errorMessage; 
        } 
    } 
    
  2. 準備的用戶對你所需要的所有活動:

    @Override 
    public void onStart() { 
        super.onStart(); 
        EventBus.getDefault().register(this); 
    } 
    
    @Override 
    public void onStop() { 
        EventBus.getDefault().unregister(this); 
        super.onStop(); 
    } 
    
  3. 在所有的活動中,顯示對話框,如果接收到的事件

    public void onEvent(ShowErrorMessageEvent event) { 
        /* Show dialog with event.getErrorMessage() from background thread */ 
    }; 
    
  4. 在你的後臺線程,發佈錯誤事件:

    EventBus.getDefault().post(new ShowErrorMessageEvent("This is an error message!")); 
    
0

您需要重置該對話框連接類型的窗口,如下圖: dialog.getWindow()的setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT );

不要忘記在清單中聲明「android.permission.SYSTEM_ALERT_WINDOW」權限。

1

這是一個實現,它允許AlertDialog顯示在當前活動活動的頂部(這是消息對話框的一個例子,但也可以用於提醒)。

public class AlertsDialogue 
{ 
    private AlertDialog.Builder alertDialogBuilder; 
    private AlertDialog alert; 

    public AlertsDialogue(Context context, String title, String message) 
    { 
     alertDialogBuilder = new AlertDialog.Builder(context); 
     alertDialogBuilder.setTitle(title); 
     alertDialogBuilder.setIcon(R.drawable.ic_launcher); 
     alertDialogBuilder.setMessage(message) 
      .setCancelable(false) 
      .setPositiveButton(context.getString(R.string.text_ok), new DialogInterface.OnClickListener() { 
       @Override 
       public void onClick(DialogInterface dialog, int which) 
       { 
        alert.dismiss(); 
       } 
      }); 

     alert = alertDialogBuilder.create(); 
     Window window = alert.getWindow(); 
     if (window != null) 
     { 
      // the important stuff.. 
      window.setType(WindowManager.LayoutParams.TYPE_TOAST); 
      alert.show(); 
     } 
     else 
      Toast.makeText(context, message, Toast.LENGTH_LONG).show(); 
    } 
} 

對話框將顯示,即使在將其用實例化的情況下不再有效,就像Toast。與new AlertsDialogue(MyActivity.this, "title", "message");

無需額外的權限是必需的AndroidManifest文件

呼叫。

相關問題