簡體   English   中英

如何通過配置更改在Android上管理藍牙連接?

[英]How to manage a Bluetooth connection on Android through configuration changes?

題:
如何管理(連接,讀取,寫入,斷開)通過配置更改持續存在的藍牙連接?

首選使用ActionBarSherlock與設備版本2.2“Froyo”兼容的解決方案。

問題...

  • BluetoothDeviceBluetoothSocket都不能保留在onSaveState

  • 為了保持我的應用程序響應 ,12秒阻止調用BluetoothSocket.connect()必須在單獨的線程上進行。 啟動Runnable是線程長任務的推薦方法,但是嘗試恢復配置更改是一場噩夢。 官方文檔指出了三種不同的解決方案。

    • 使用不推薦使用的getLastNonConfigurationInstance() (嚴重?!)。

    • BluetoothChat Sample一樣設置android:configChanges="keyboardHidden|orientation" 但是,這並未考慮所有類型的配置更改。

    • 取消並重新啟動任務,例如貨架示例 在這種情況下,這可能會浪費另外12秒。

更新1

  • 進一步的研究使我得到了asyncTaskLoader ,但似乎這只能在完成時更新UI,並且無法提供更新。

  • BluetoothHDP示例使用服務。 服務似乎側重於進程間通信以及持續超出活動生命周期的需要。 我不需要這些功能。

更新2

正如Reuben所指出的Fragment.setRetainInstance(bool)已經取代了不推薦使用的getLastNonConfigurationInstance() 在這一點上,似乎最好的選擇是使用setRetainInstance(true)創建一個持久的非UI片段。

我會通過使用可以處理您的藍牙連接的Service來解決此問題,並使該服務與您的活動對話,如本答案中所述。

然后,您可以使用ASyncTask簡單地顯示/隱藏對話框,並在輪換時取消/重新啟動ASyncTasks,這由您提到的Shelves Example完成。

服務並不是那么可怕,可能是解決問題的最佳工具。

切勿將App Model(邏輯或數據)放在Visual / UI組件中。 如你所見,他們來去匆匆而且改變。

保留非UI相關內容的地方,如數據集合,實時連接,線程等:

  • Application類。 包含所有其他組件的生命周期。 幾乎像一個全球單身人士。 您可以將其用於臨時存儲。

例:

public class App extends Application {

  private static Beer sBeer;

  public static void brbHoldMyBeer(Beer b){
    sBeer = b;
  }

  public static Beer imBackWheresMyBeer(){
    return sBeer;
  }

}

此外,在Application類中使用靜態線程Executor服務將有助於保留正在運行的任務。

  • 正在運行的后台服務。 哪些活動,片段等可以綁定/取消綁定,以及發布命令/請求。 這是App廣泛運行的進程和數據的推薦位置。

  • 具有setRetainInstance(true)非可視片段。 這里的非可視化意味着它是一個虛擬片段,它附加到Activity但不顯示任何視圖。 它僅用作Activity的可保留對象持有者。 建議用於活動范圍的流程和數據。

您可以嘗試使用可以處理所有內容的單例模式 ,並在必要時調用主要活動。

因此,獲取MySingleton對象的實例是一種靜態方法,每次調用getInstance時都是相同的實例。 您可以“存儲”其中的所有藍牙對象,它不會被銷毀並且可以從每個活動訪問。

public class MySingleton { 
    private static MySingleton instance; 
    public static MySingleton getInstance() { 
        if (null == instance) { 
            instance = new MySingleton(); 
        } 
    return instance; 
} 

    private MySingleton() { 
    } 
}

這有很多解決方案。 如果您沒有使用Fragments,那么最簡單的選項是覆蓋onRetainNonConfigurationInstance()。 不要緊,API已被棄用,這只是因為他們希望你使用Fragments(公平地說,Fragment.setRetainInstance()使整個問題成為應該總是這樣的問題)。 這個API很長一段時間都不會去。

我要做的是覆蓋onRetainNonConfiguration()以返回'this',即對死活動實例的引用,然后從onCreate()復制你需要的對象引用,即:

Object obj = getLastNonConfigurationInstance();
if (obj != null) {
    MyActivity deadActivity = (MyActivity)obj;
    this.foo = deadActivity.foo;
    this.bar = deadActivity.bar;
    ...
}

或者你可以使用服務,但我個人不喜歡它們。 毫無疑問,對於執行跨進程的東西很有用,但除此之外,它們是尋找問題的解決方案。

最后,作為一般性的程序問題,您可以安全地將“全局”數據填充到您的應用程序上下文中。 為此,您將android.app.Application子類化,並在清單中使用<application android:name =“MyApp”>屬性。 在這里保留對全局靜態數據中的Application對象的引用是有用的,因此AsyncTasks和其他無上下文代碼總是可以到達Application上下文而不必無緣無故地傳遞Context參數。

class MyApp extends Application {
...

    public static MyApp context;
    ...

    @Override
    public void onCreate() {
        super.onCreate();

        context = this;

        ... set up global data here ...
    }
...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM