Использование bluetooth framework в Android SDK чрезвычайно замедляет работу системы при удалении приложения

#android #bluetooth #android-2.2-froyo

#Android #bluetooth #android-2.2-froyo

Вопрос:

ОБНОВЛЕНИЕ: я понял, что если я закрою Bluetooth перед удалением приложения, проблема больше не останется, так что действительно есть ресурс, который не освобождается при завершении работы приложения.

ОБНОВЛЕНИЕ 2: вот проект eclipse на случай, если кто-нибудь захочет попробовать тестовое приложение: http://minus.com/dRRJ2nvzmyN3F.zip

Я создал простое приложение, которое получает данные с моего компьютера с помощью Bluetooth и отображает их в текстовом представлении. Приложение работает нормально, так как я могу видеть полученные данные в текстовом представлении. Проблема в том, что во время удаления приложения система сильно замедляется и остается неизменной после завершения удаления. То же самое происходит, когда я загружаю новую версию проекта с помощью Eclipse. Я экспортировал и подписал приложение, чтобы запустить его в режиме выпуска, и то же самое продолжает происходить при удалении приложения. В конце концов мне нужно перезагрузить устройство. Я столкнулся с этой ситуацией только при удалении или обновлении приложения, как я уже сказал. Я несколько раз завершаю и повторно запускаю приложение, и оно работает нормально и не замедляет работу системы. Возможно, выделенный системный ресурс не освобождается, но я не смог его найти. Устройство представляет собой Samsung Galaxy GIO (S5660), на нем установлена версия Android 2.2, а приложение скомпилировано с использованием minSdkVersion =»8″. Мой проект содержит три класса, которые приведены ниже:

BluetoothTestAppActivity.java

 package com.test.bluetoothtestapp;

import java.util.UUID;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class BluetoothTestAppActivity extends Activity {
    /** Called when the activity is first created. */
    private BluetoothServerThread mBtServerThread;
    private Handler mHandler;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mHandler = new Handler(){
            public void handleMessage(Message msg){
                Bundle bundle = msg.getData();
                String data = bundle.getString("data");
                TextView tv = (TextView)findViewById(R.id.hello);
                tv.setText(data);
            }
        };

        // see http://code.google.com/p/android/issues/detail?id=16587 for why we are calling this method on UI thread
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        adapter.cancelDiscovery();

        mBtServerThread = new BluetoothServerThread(adapter, mHandler,getString(R.string.bt_service_name), 
                UUID.fromString(getString(R.string.bt_service_uuid)));
        mBtServerThread.start();
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        try{
            if(mBtServerThread != null){
                mBtServerThread.cancel();
            }
        }
        catch(Exception ex){
            Log.e("BluetoothTestAppActivity Exception", ex.getMessage());
        }
    }
}
  

BluetoothServerThread.java

 package com.test.bluetoothtestapp;

import java.io.IOException;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.util.Log;

public class BluetoothServerThread extends Thread{

    private BluetoothServerSocket mServerSocket;
    private String mServiceName;
    private UUID mUUID;
    private BluetoothAdapter mAdapter;
    private BluetoothDataTransferThread mTransferThread;
    private Handler mHandler;

    public BluetoothServerThread(BluetoothAdapter adapter,Handler handler ,String serviceName, UUID uuid){
        mHandler = handler;
        mAdapter = adapter;
        mServerSocket = null;
        mServiceName = serviceName;
        mUUID = uuid;
    }

    public void run(){

            BluetoothSocket socket = null;
            try{
                mServerSocket = mAdapter.listenUsingRfcommWithServiceRecord(mServiceName,mUUID);
                socket = mServerSocket.accept();
                if(socket != null){
                    mTransferThread = new BluetoothDataTransferThread(socket, mHandler);
                    mTransferThread.start();
                    mServerSocket.close();

                }
            }
            catch(IOException ex){
                Log.e("BluetoothServerThread run",ex.getMessage());

            }
    }

    public void cancel(){
        try{
            if(mTransferThread != null){
                mTransferThread.cancel();
            }
            mServerSocket.close();
        }
        catch(IOException ex){
            Log.e("BluetoothServertThread IOException cancel",ex.getMessage());
        }
        catch(Exception ex){
            Log.e("BluetoothServertThread Exception cancel",ex.getMessage());
        }
    }


}
  

BluetoothDataTransferThread.java

 package com.test.bluetoothtestapp;

import java.io.IOException;
import java.io.InputStream;

import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class BluetoothDataTransferThread extends Thread{
    private BluetoothSocket mSocket;
    private InputStream mInStream;
    private Handler mHandler;

    public BluetoothDataTransferThread(BluetoothSocket socket, Handler handler){
        mHandler = handler;
        mSocket = socket;
        InputStream tmpIn = null;

        try{
            tmpIn = mSocket.getInputStream();
        }
        catch(Exception ex){
            Log.e("BluetoothDataTransferThread consructor",ex.getMessage());
        }

        mInStream = tmpIn;
    }

    public void run(){
        byte[] buffer = new byte[1024];
        int count = -1;

        while(true){
            try{
                count = mInStream.read(buffer);
                if(count != -1){

                    String str = new String(buffer, 0, count);
                    Message msg = Message.obtain(mHandler);
                    Bundle bundle = new Bundle();
                    bundle.putString("data", "data read: " str);
                    msg.setData(bundle);
                    msg.sendToTarget();
                }
                else{
                    break;
                }
            }
            catch(IOException ex){
                Log.e("BluetoothDataTransferThread run",ex.getMessage());
                break;
            }
        }
    }

    public void cancel(){
        try{
            mSocket.close();
        }
        catch(IOException ex){
            Log.e("BluetoothDataTransferThread IOException cancel",ex.getMessage());
        }
        catch(Exception ex){
            Log.e("BluetoothDataTransferThread Exception cancel",ex.getMessage());
        }
    }
}
  

Я изменил метод запуска BluetoothServerThread.java следующим образом:

 public void run(){

        BluetoothSocket socket = null;
        try{
            mServerSocket = mAdapter.listenUsingRfcommWithServiceRecord(mServiceName,mUUID);
            socket = mServerSocket.accept();
            if(socket != null){
                mServerSocket.close();
                socket.close();

            }
        }
        catch(IOException ex){
            Log.e("BluetoothServerThread run",ex.getMessage());

        }

    }
  

Обратите внимание, что я немедленно закрываю соединение после его установки. В этом случае поток передачи данных вообще не запускается, а поток сервера завершается (я вижу, что он завершается с использованием режима отладки в Eclipse). Таким образом, не осталось бы ни одного потока для блокировки или выделения каких-либо системных ресурсов, но проблема остается как есть.

Любая помощь будет оценена. Спасибо за ваше время.

Ответ №1:

Я склонен думать, что вы создаете более одного потока. onDestroy не поддерживается для вызова в общих жизненных циклах, поэтому в вашем onCreate проверьте, существует ли mBtServerThread уже и запущен ли поток. Если это произойдет, завершите поток, затем запустите другой. Не могу гарантировать, что это так, но это имело бы смысл.

Комментарии:

1. Конечно, вы видите выходы, но может быть 3 открытых потока и 1 выход. onCreate будет вызываться несколько раз в вашем приложении, а ondestroy может вообще не вызываться. В настоящее время это означает, что создается более одного потока, а последний уничтожается при условии, что ondestroy вызывается при удалении