Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android蓝牙连接工具_Java_Android_Multithreading_Bluetooth - Fatal编程技术网

Java Android蓝牙连接工具

Java Android蓝牙连接工具,java,android,multithreading,bluetooth,Java,Android,Multithreading,Bluetooth,我的应用程序可以连接蓝牙设备并读取数据,但当蓝牙离线时,我的应用程序将冻结屏幕,直到找到设备或超时。以下是主要功能: Manifest.xml <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <application

我的应用程序可以连接蓝牙设备并读取数据,但当蓝牙离线时,我的应用程序将冻结屏幕,直到找到设备或超时。以下是主要功能:

Manifest.xml

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyGatewayService"
            android:enabled="true"
            android:exported="true"></service>
    </application>

</manifest>
MyGateWayService.java

public class MyGatewayService extends AbstractGatewayService{
    private static final String TAG = MyGatewayService.class.getName();
    private BluetoothDevice dev = null;
    private BluetoothSocket sock = null;

@Override
protected void onHandleIntent(Intent intent) {
      //what should I put in here?
}

    @Override
    public void startService() throws IOException {
        final String remoteDevice = getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE).getString(Constants.SHARED_PREFERENCES_BLUETOOTH_SELECTION_ADDRESS_KEY, "");

        if (remoteDevice == null||"".equals(remoteDevice)){
            Toast.makeText(getApplicationContext(),"No Bluetooth device selected...",Toast.LENGTH_SHORT).show();
            Log.e(TAG,"No Bluetooth device selected...");
            stopService();
            throw new IOException();
        }else{
            final BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
            dev = btAdapter.getRemoteDevice(remoteDevice);
            Log.d(TAG,"Stop bluetooth discovery...");
            btAdapter.cancelDiscovery();
            Log.d(TAG,"Start Service..");
            try{
                startServiceConnection();
            }catch (Exception e){
                Log.e(TAG, "There was an error while establishing connection..." + e.getMessage());



           stopService();
            throw new IOException();
        }
    }
}

    private void startServiceConnection() throws IOException, InterruptedException {
        Log.d(TAG, "Start the connection");
        isRunning = true;

        try{
            sock = com.ibm.us.wuxiaosh.androidbluetoothdemo.BluetoothManager.connect(dev);
        }catch (Exception e2){
            Log.e(TAG, "There was an error while connecting... stop...");
            stopService();
            throw new IOException();
        }


    }

    @Override
    protected void executeQueue(){
        Log.d(TAG,"Executing...");
        while(!Thread.currentThread().isInterrupted()){
            //Log.d(TAG,"Executing ....................");
        }
    }
    @Override
    public void stopService() {
        isRunning = false;

        if (sock!=null){
            try{
                sock.close();
            }catch (IOException e){
                Log.e(TAG, e.getMessage());
            }
            stopSelf();
        }
    }
}
主要功能:

@Override
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d(TAG, className.toString() + " service is bound");
            isServiceBound = true;
            service = ((AbstractGatewayService.AbstractGatewayServiceBinder) binder).getService();
            service.setContext(MainActivity.this);
            Log.d(TAG, "Starting live data");

            try{
                service.startService();

                Log.d(TAG , "Connected");


            } catch (IOException ioe){
                Log.e(TAG, "Failure Starting Live Data");
                doUnbindService();
            }

        }
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
        @Override
        public void onServiceDisconnected(ComponentName className) {
            Log.d(TAG, " service is unbound");
            isServiceBound = false;
        }
    };




    private void doBindService(){
        if(!isServiceBound){
            Log.d(TAG, "Binding OBD Service..");

            Log.e(TAG,"start intent 1");
            Intent serviceIntent = new Intent(this, MyGatewayService.class);
            Log.e(TAG,"intent finished");
            bindService(serviceIntent,serviceConn, Context.BIND_AUTO_CREATE);
            Log.e(TAG,"bindService");
        }
    }

    private void doUnbindService(){
        if(isServiceBound){
            if (service.isRunning()){
                service.stopService();

                Log.d(TAG,"Ready");
            }
            Log.e(TAG, "Unbinding OBD Service...");
            unbindService(serviceConn);
            isServiceBound = false;
            Log.e(TAG, "Disconnected");
        }
    }
更新: 另一个文件:AbstractGateWayService&将其更改为extends intentService

public abstract class AbstractGatewayService extends IntentService{
    private static final String TAG = AbstractGatewayService.class.getName();
    private final IBinder binder = new AbstractGatewayServiceBinder();
    protected Context ctx;
    protected boolean isRunning = false;

    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            Log.e(TAG, "Thread Run...");
                long futureTime = System.currentTimeMillis()+10000;
                while(System.currentTimeMillis()<futureTime) {
                    executeQueue();
                }
        }
    });

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Creating Service...");
        t.start();
        Log.d(TAG, "Service Creating...");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"Destroying service");
        t.interrupt();
        Log.d(TAG,"Service Destroyed");
    }

    class AbstractGatewayServiceBinder extends Binder {
        public AbstractGatewayService getService(){
            return AbstractGatewayService.this;
        }
    }
    public boolean isRunning() {
        return isRunning;
    }

    public void setContext(Context c) {
        ctx = c;
    }

    abstract protected void executeQueue();

    abstract public void startService() throws IOException;

    abstract public void stopService();
}
公共抽象类AbstractGatewayService扩展了IntentService{
私有静态最终字符串标记=AbstractGatewayService.class.getName();
私有最终IBinder绑定器=新的AbstractGatewayServiceBinder();
保护上下文ctx;
受保护的布尔值isRunning=false;
线程t=新线程(新的可运行线程(){
@凌驾
公开募捐{
Log.e(标记“线程运行…”);
long futureTime=System.currentTimeMillis()+10000;

而(System.currentTimeMillis()您的问题是调用了
startService()中的套接字连接逻辑(正如您正确推断的,这是一个阻塞调用)
方法。Android中的
服务
虽然在逻辑上与应用程序的主流程分离,但默认情况下在同一
线程上运行。通过在服务中调用阻止调用,可以阻止UI线程

您有多种解决方案可供选择:

  • 使用
    IntentService
    而不是
    Service
    IntentService
    有自己的处理程序并在单独的线程上运行
  • 将逻辑保留在当前点,但将其包装在
    异步任务中
    重要:您需要包装逻辑本身,而不是
    服务
    启动逻辑
  • 完全删除
    服务
    部分,将逻辑放入
    异步任务

取决于您的选择,
IntentService
解决方案似乎最适合更复杂的应用程序,而创建
AsyncTask
将是最快速、最直接的方法:-)

Hi@Kelevandos谢谢你的回复,我想我会使用IntentService,我还更新了我的帖子,加入了我的更改并添加了抽象服务类,因为我已经实现了startService()方法,我应该将其移动到onHandleIntent中吗?我想知道我应该将什么放入onHandleIntent方法中。谢谢您可以尝试将所有逻辑移动到其中并检查其是否有效。您的示例中有大量代码,因此如果没有更广泛的上下文,我无法说是否有效:-)此外,对于IntentService设置,您可能希望创建并使用带有循环器的处理程序,而不是自定义线程。
public abstract class AbstractGatewayService extends IntentService{
    private static final String TAG = AbstractGatewayService.class.getName();
    private final IBinder binder = new AbstractGatewayServiceBinder();
    protected Context ctx;
    protected boolean isRunning = false;

    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            Log.e(TAG, "Thread Run...");
                long futureTime = System.currentTimeMillis()+10000;
                while(System.currentTimeMillis()<futureTime) {
                    executeQueue();
                }
        }
    });

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Creating Service...");
        t.start();
        Log.d(TAG, "Service Creating...");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"Destroying service");
        t.interrupt();
        Log.d(TAG,"Service Destroyed");
    }

    class AbstractGatewayServiceBinder extends Binder {
        public AbstractGatewayService getService(){
            return AbstractGatewayService.this;
        }
    }
    public boolean isRunning() {
        return isRunning;
    }

    public void setContext(Context c) {
        ctx = c;
    }

    abstract protected void executeQueue();

    abstract public void startService() throws IOException;

    abstract public void stopService();
}