防止在蓝牙设备连接时产生新的 Activity
Prevent a new Activity from spawning when a Bluetooth device connects
目标
- 如果蓝牙设备连接,并且没有 Activity 是 运行ning,则启动 Activity
- 如果蓝牙设备连接,并且 Activity 已经 运行ning,请连接到已经 运行ning Activity
问题
- 设备一连接,新的 Activity 就会启动。我无法使应用重用相同 Activity。
我设法解决的问题
- 如果蓝牙设备连接,并且没有 Activity 是 运行ning,则启动 Activity
问题体现在 BroadCastReceivers 的使用中,而 BroadCastReceivers 又会启动 Activity 使用意图。出于某种原因,Activity 在其生命周期中保持 运行ning,当新设备连接时产生新的 windows。
我仅在带有 Android N 的 Nexus 6P 上对此进行了测试。我还不知道此实现对任何其他设备意味着什么。但我至少需要在 one 设备上运行它。
清单
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.VIBRATE" />
<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>
<activity android:name=".BtActivity" />
<receiver android:name=".BtConnectionBroadcastReceiver" android:priority="100000">
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.VOLUME_CHANGED_ACTION" />
</intent-filter>
</receiver>
</application>
BtConnectionBroadcastReceiver
public class BtConnectionBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "BT";
public static final String BROADCAST_ACTION_CONNECTED = "CONNECTED";
public static final String BROADCAST_ACTION_DISCONNECTED = "DISCONNECTED";
SharedPreferences mSharedPreferences;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
// Get the BluetoothDevice object from the Intent
Log.d(TAG, "DEVICE CONNECTED");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d("DEVICE NAME", device.getName());
Log.d("DEVICE ADDRESS", device.getAddress());
Intent i = new Intent(context, BtActivity.class);
context.startActivity(i);
} else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
Log.d(TAG, "DEVICE DISCONNECTED");
intent = new Intent();
intent.setAction(BtConnectionBroadcastReceiver.BROADCAST_ACTION_DISCONNECTED);
context.sendBroadcast(intent);
}
}
BtActivity
public class BtActivity extends AppCompatActivity {
private static final String TAG = "BT";
Window mWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt);
Log.d(TAG, "onCreate");
IntentFilter filter = new IntentFilter(BtConnectionBroadcastReceiver.INTENT_FILTER);
filter.addAction(BtConnectionBroadcastReceiver.BROADCAST_ACTION_CONNECTED);
filter.addAction(BtConnectionBroadcastReceiver.BROADCAST_ACTION_DISCONNECTED);
//registerReceiver(mReceiver, filter);
mWindow = getWindow();
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
//params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF;
params.screenBrightness = 0.2f;
mWindow.setAttributes(params);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
mWindow.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE);
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
}
当我运行这段代码时,我得到以下链:
- Start MainActivity(不包含,它只包含一个 activity 默认主布局,以便注册应用程序接收器)
- 打开蓝牙设备(之前已经配对,所以 android 知道)
- 等到它连接上并得到这个:
- 设备已连接
- onCreate
- 恢复
我不明白为什么 activity 在此时重新启动。 activity已经运行ning,BroadcastReceiver只发送一个广播给已经运行ning的activity。我不明白为什么 Activity 会自行终止并 然后 再次重启。
尝试将启动模式设置为正在启动的 activity。
android:launchMode="singleTop"
如果此 activity 当前是该任务中最顶层的 activity 并且 activity 的 onNewIntent() 方法,这会将意图传递给同一个 activity 实例将被调用而不是 onCreate()。并通过传递 intent extras 来管理功能。如果此 activity 不是其任务中最顶层的 activity 或者根本没有 activity 运行,则将创建 activity 的新实例onCreate() 和 onResume() 将被调用。
也可以根据需要使用"singleTask"/"singleInstance"等其他启动方式
希望对您有所帮助。
目标
- 如果蓝牙设备连接,并且没有 Activity 是 运行ning,则启动 Activity
- 如果蓝牙设备连接,并且 Activity 已经 运行ning,请连接到已经 运行ning Activity
问题
- 设备一连接,新的 Activity 就会启动。我无法使应用重用相同 Activity。
我设法解决的问题
- 如果蓝牙设备连接,并且没有 Activity 是 运行ning,则启动 Activity
问题体现在 BroadCastReceivers 的使用中,而 BroadCastReceivers 又会启动 Activity 使用意图。出于某种原因,Activity 在其生命周期中保持 运行ning,当新设备连接时产生新的 windows。
我仅在带有 Android N 的 Nexus 6P 上对此进行了测试。我还不知道此实现对任何其他设备意味着什么。但我至少需要在 one 设备上运行它。
清单
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.VIBRATE" />
<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>
<activity android:name=".BtActivity" />
<receiver android:name=".BtConnectionBroadcastReceiver" android:priority="100000">
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.VOLUME_CHANGED_ACTION" />
</intent-filter>
</receiver>
</application>
BtConnectionBroadcastReceiver
public class BtConnectionBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "BT";
public static final String BROADCAST_ACTION_CONNECTED = "CONNECTED";
public static final String BROADCAST_ACTION_DISCONNECTED = "DISCONNECTED";
SharedPreferences mSharedPreferences;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
// Get the BluetoothDevice object from the Intent
Log.d(TAG, "DEVICE CONNECTED");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d("DEVICE NAME", device.getName());
Log.d("DEVICE ADDRESS", device.getAddress());
Intent i = new Intent(context, BtActivity.class);
context.startActivity(i);
} else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
Log.d(TAG, "DEVICE DISCONNECTED");
intent = new Intent();
intent.setAction(BtConnectionBroadcastReceiver.BROADCAST_ACTION_DISCONNECTED);
context.sendBroadcast(intent);
}
}
BtActivity
public class BtActivity extends AppCompatActivity {
private static final String TAG = "BT";
Window mWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt);
Log.d(TAG, "onCreate");
IntentFilter filter = new IntentFilter(BtConnectionBroadcastReceiver.INTENT_FILTER);
filter.addAction(BtConnectionBroadcastReceiver.BROADCAST_ACTION_CONNECTED);
filter.addAction(BtConnectionBroadcastReceiver.BROADCAST_ACTION_DISCONNECTED);
//registerReceiver(mReceiver, filter);
mWindow = getWindow();
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
//params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF;
params.screenBrightness = 0.2f;
mWindow.setAttributes(params);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
mWindow.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE);
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
}
当我运行这段代码时,我得到以下链:
- Start MainActivity(不包含,它只包含一个 activity 默认主布局,以便注册应用程序接收器)
- 打开蓝牙设备(之前已经配对,所以 android 知道)
- 等到它连接上并得到这个:
- 设备已连接
- onCreate
- 恢复
我不明白为什么 activity 在此时重新启动。 activity已经运行ning,BroadcastReceiver只发送一个广播给已经运行ning的activity。我不明白为什么 Activity 会自行终止并 然后 再次重启。
尝试将启动模式设置为正在启动的 activity。
android:launchMode="singleTop"
如果此 activity 当前是该任务中最顶层的 activity 并且 activity 的 onNewIntent() 方法,这会将意图传递给同一个 activity 实例将被调用而不是 onCreate()。并通过传递 intent extras 来管理功能。如果此 activity 不是其任务中最顶层的 activity 或者根本没有 activity 运行,则将创建 activity 的新实例onCreate() 和 onResume() 将被调用。
也可以根据需要使用"singleTask"/"singleInstance"等其他启动方式
希望对您有所帮助。