Служба все еще работает, когда экран заблокирован

У меня есть экран подключения, на котором у меня есть кнопка поиска, после того, как я щелкнул по ней, опубликован список обнаруживаемых устройств, я щелкаю по нужному устройству для установления соединения и подключения, соединение устанавливается, и когда я блокирую экран, соединение потеряно, как я могу улучшить свой код, чтобы служба все еще работала? Вот как я пытался это реализовать, onCreate(), onStart() и onResume() также реализованы внутри launchApplication().

 public static void launchActivity(Context context, String deviceAddress){
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    mCurrentDeviceAddress = deviceAddress; //getIntent().getExtras().getString(ConnectionScreen.PREFS_DEVICE_ADDR);
    mChatService = new BluetoothMeterService(context, mHandler);
    connectDevice();
    if (mChatService != null) {
        if (mChatService.getState() == BluetoothMeterService.STATE_NONE) {
            mChatService.start();
        }
    }

}


// Automatically try to connec with the known mac address;
private static class ConnectThread extends Thread {

    private final BluetoothDevice device;

    public ConnectThread(BluetoothDevice d) {
        this.device = d;
    }

    public void run() {

        while (mConnectThread == Thread.currentThread()) {
            if (mChatService.getState() == BluetoothMeterService.STATE_CONNECTED) {
                Log.e(TAG, "STATE_CONNECTED");
                break;
            } else if (mChatService.getState() == BluetoothMeterService.STATE_CONNECTING) {
                try {
                    //Thread.sleep(2000);
                    Log.e(TAG, "STATE_CONNECTING");
                    mChatService.connect(device);
                } catch (Exception e) {
                    // Log.e(TAG, e.getMessage());
                }
            } else
                try {

                    Log.e(TAG, "STATE_DISCONECTED");
                    mChatService.start();
                    Thread.sleep(3000);
                } catch (Exception e) {
                    // Log.e(TAG, e.getMessage());
                    Thread.currentThread().interrupt();
                }
        }
    }
}


// create the bluetooth device object, and try to connect with it
// consistantly and automatically.
private static void connectDevice() {
    if (mCurrentDeviceAddress == null) {
        Toast.makeText(context, "Bluetooth MAC address is not assigned.",
                Toast.LENGTH_SHORT).show();
        //context.finish();
        return;
    }
    BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(mCurrentDeviceAddress);
    // showDialog(Dialog_Connect);
    mConnectThread = new ConnectThread(device);
    mConnectThread.start();
}




// The Handler that gets information back from the BluetoothMeterService
private static final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Log.e(TAG, msg.toString());
        switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                switch (msg.arg1) {
                    case BluetoothMeterService.STATE_CONNECTED:
                        Log.e(TAG, "handler - STATE_CONNECTED");
                        for(CustomizedBluetoothDevice device : mDeviceList){
                            if(device.getAddress() == mCurrentDeviceAddress){
                                device.setStatus(BluetoothMeterService.STATE_CONNECTED);
                            }
                        }
                        updateUI(/*mDeviceList*/);
                        // mTextViewTitle.setText("Device: " + mConnectedDeviceName);
                        // mTextViewStatus.setText(R.string.title_connected_to);
                        break;
                    case BluetoothMeterService.STATE_CONNECTING:
                        Log.e(TAG, "handler - STATE_CONNECTING");
                        for(CustomizedBluetoothDevice device : mDeviceList){
                            if(device.getAddress() == mCurrentDeviceAddress){
                                device.setStatus(BluetoothMeterService.STATE_CONNECTING);
                            }
                        }
                        updateUI(/*mDeviceList*/);
                        // mTextViewStatus.setText(R.string.title_connecting);
                        break;
                    case BluetoothMeterService.STATE_NONE:
                        Log.e(TAG, "handler - STATE_NONE");
                        for(CustomizedBluetoothDevice device : mDeviceList){
                            if(device.getAddress() == mCurrentDeviceAddress){
                                device.setStatus(BluetoothMeterService.STATE_NONE);
                            }
                        }
                        updateUI(/*mDeviceList*/);
                        // mTextViewStatus.setText(R.string.title_not_connected);
                        break;
                    case BluetoothMeterService.STATE_DISCONNECTING:
                        Log.e(TAG, "handler - STATE_DISCONNECTING");
                        for(CustomizedBluetoothDevice device : mDeviceList){
                            if(device.getAddress() == mCurrentDeviceAddress){
                                device.setStatus(BluetoothMeterService.STATE_DISCONNECTING);
                            }
                        }
                        updateUI(/*mDeviceList*/);
                        break;
                }
                break;
            case MESSAGE_WRITE:
                break;
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                String readMessage = new String(readBuf, 0, msg.arg1);
                Log.e(TAG, "handler - MESSAGE_READ " + readMessage);
                // bufferMessege += readMessage;
               /* if (mMessage != null) {
                    mMessage.add(new CustomizedMessage(readMessage, true));
                    updateUI();
                }*/
                // bufferMessege = "";
                break;
            case MESSAGE_DEVICE_NAME:
                Log.e(TAG, "handler - MESSAGE_READ " + MESSAGE_DEVICE_NAME);
                // save the connected device's name
                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                break;
            case MESSAGE_TOAST:
                Log.e(TAG, "handler - MESSAGE_READ " + MESSAGE_TOAST);

                break;
        }
    }
};

public void stopActivity(){
    if (mChatService != null)
    {
        mChatService.stop();
        mChatService = null;
    }
}

2 ответа

Решение

Это на самом деле нормально. Как далеко вы выходите из приложения, и жизненный цикл Android вызывает onDestroy() Метод, все соединения должны быть отключены. Поэтому вам нужен процесс, который работает в фоновом режиме. Здесь вы можете использовать Android Service составная часть. Это будет работать до тех пор, пока вы используете ресурсы, как только закончится процесс Service собирается закрыть. Так что все зависит от того, что вам нужно. Если вам нужен фоновый сервис, который будет работать вечно в фоновом режиме, вы должны использовать startForeground() метод Service,

Больше информации о Service здесь: http://developer.android.com/guide/components/services.html

Я предполагаю, что launchActivity вызывается из одного из методов жизненного цикла вашей деятельности.

если это так - вы в основном создаете фоновую логику, которая "привязана" к действию, то есть компоненту пользовательского интерфейса. Это плохая идея.

Зачем?

Потому что Android довольно быстро восстанавливает фоновые действия вместе с порожденными ими потоками, когда ресурсы заканчиваются.

Что вы должны сделать, это явно сообщить Android, что эта логика должна рассматриваться как фоновая логика, то есть не связана с видимостью активности на включенном экране.

Для этого вам необходимо объявить услугу.

В декларации:

<service
  android:name="MyConnectionService"
  android:icon="@drawable/icon"
  android:label="@string/service_name"  >
</service> 

И в коде:

public class MyConnectionService extends Service {

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
       // <------------ place connection logic here
  }

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

Если вы хотите, чтобы ваша логика выполнялась отдельно от потока пользовательского интерфейса (как я полагаю, вы делаете), используйте IntentService

public class MyConnectionService extends IntentService {

  @Override
  protected void onHandleIntent(Intent intent) {
       // <--------- run connection logic on a dedicated thread here
  }
}

Наконец, если вы хотите, чтобы ваш сервис всегда оставался в эфире, несмотря ни на что (и большинству приложений такое поведение не требуется), объявите ваш сервис как приоритетный:

Notification notification = new Notification(R.drawable.icon, getText(R.string.msg_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MyConnectionService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(SERVICE_NOTIFICATION_ID, notification);
Другие вопросы по тегам