Использование bluetooth framework в Android SDK значительно замедляет работу системы при удалении приложения - PullRequest
0 голосов
/ 10 октября 2011

UPDATE: Я понял, что если я закрою блютуз перед удалением приложения, проблема больше не останется, поэтому действительно есть ресурс, который не освобождается при выходе из приложения.

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

Я создал простое приложение, которое получает данные с моего компьютера с помощью Bluetooth и отображает их в TextView. Приложение работает нормально, так как я могу видеть полученные данные в TextView. Проблема заключается в том, что во время удаления приложения система сильно замедляется и остается такой же после завершения удаления. То же самое происходит, когда я загружаю новую версию проекта с использованием Eclipse. Я экспортировал и подписал приложение, чтобы запустить его в режиме выпуска, и при удалении приложения происходит то же самое. Я должен перезагрузить устройство в конце концов. Я только сталкивался с этой ситуацией при удалении или обновлении приложения, как я сказал. Я закрываю и перезапускаю приложение несколько раз, и оно работает нормально и не замедляет работу системы. Возможно, выделенный системный ресурс не освобождается, но я не смог его найти. Это устройство Samsung Galaxy GIO (S5660), на нем установлена ​​версия Android 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 Ответ

1 голос
/ 10 октября 2011

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

...