繁体   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