Android activity 结果未被检查
Android activity results not being checked
我有一个应用 LoginActivity
-> MainActivity
。 Main activity 是这样启动的,因为我不想将 LoginActivity
添加到堆栈中:
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
启动 MainActivity
后,在 onResume
中,我检查蓝牙是否已启用。如果没有,请询问用户是否要启用它(这发生在助手 class btHelper
):
public void enableBT(){
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
mainActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
所以在这里,我需要检查用户选择的内容。如果他们选择是,那么我将启用 BT 并注册一个广播接收器。如果他们选择否,我想完成 MainActivity
并返回 LoginActivity
:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == btHelper.REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
//Register broadcast receiver once BT is enabled
btHelper.registerBroadcastReceiver();
} else {
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finishAffinity();
}
}
}
当我 运行 应用程序时,如果用户选择是,则一切正常。如果他们选择“否”,那么一切正常,他们将进入“登录”屏幕。然而,当他们再次登录时,当然会出现对话框询问他们是否要启用 BT,但是如果他们第二次选择否,那么他们就不会被带到登录 - 对话框只是重新显示
我看过这个问题 here 但它似乎不适用,因为我没有以编程方式设置任何结果。出于某种原因,用户选择 No/Deny 只会在第一次时得到正确检查,而在第二次
时则不会
考虑到当我单击 No/Deny 时对话框再次显示,我想也许 onResume()
被再次调用从而调用 enableBT()
?我不确定问题是否出在类似问题上或我处理活动之间转换的方式
编辑:
我已经缩小了问题范围。每当调用 onActivityResult
时,我添加了一行以注销 resultCode
值。在第一个 运行 期间,resultCode
得到正确显示,但在重新启动 MainActivity
后的第二个 运行 上,没有任何代码被记录。通过更多测试,似乎在第二次 运行 每当我点击 No/Deny 时,就会调用 enableBT
/onResume
而不是首先检查结果代码以确定它应该是什么做 - 它只是自动重新启动 activity/fragment。这是否意味着 onActivityResult
没有被调用或没有结果代码?
EDIT2:下面添加了完整代码...
登录活动:
public class LoginActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Check if this is a fresh app launch, or a launcher click after app minimize
if (!isTaskRoot()
&& getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
finish();
return;
}
setContentView(R.layout.activity_login);
coordinatorLayoutView = findViewById(R.id.coordinator_layout_login);
//get views for textboxes and buttons
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//perform some password checking, then login
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
}
}
主要活动:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get fragment manager
fragmentManager = getSupportFragmentManager();
//Start the initial fragment
connectFragment = new ConnectFragment();
addFragment(connectFragment, false);
//Set navigation drawer/menu here
//Create bluetooth helper
btHelper = BTHelper.getInstance(this);
}
@Override
protected void onResume(){
super.onResume();
//Check and enable bluetooth
if (btHelper.getBTAdapter() == null) {
//Show alert here saying bluetooth is required, when OK is pressed, invoke `quitToLogin()`
} else {
//If bluetooth is not enabled, ask to enable it
btHelper.enableBT();
}
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy called");
super.onDestroy();
btHelper.unregisterBroadcastReceiver();
}
public void addFragment(Fragment fragment, Boolean addToBackStack) {
if (fragment != null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//Check getFragments() == null to prevent the initial blank
//fragment (before 'Connect' fragment is displayed) from being added to the backstack
if (fragmentManager.getFragments() == null || !addToBackStack) {
fragmentTransaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName())
.commit();
} else {
fragmentTransaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName())
.addToBackStack(null)
.commit();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "Result code: " + Integer.toString(resultCode));
if (requestCode == btHelper.REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
//Register broadcast receiver once BT is enabled
btHelper.registerBroadcastReceiver();
} else {
quitToLogin();
}
} else if (requestCode == btHelper.REQUEST_ENABLE_DISCOVERABLE) {
if (resultCode == 60) { //result code is discoverable time set in helper
//Start discovery
btHelper.startDiscovery();
} else {
//do other things
}
}
}
public void quitToLogin(){
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finishAffinity();
}
}
BTHelper:
public class BTHelper {
public static final String TAG = "BTHelper";
private static BTHelper sInstance;
Activity mainActivity;
private BluetoothAdapter mBluetoothAdapter;
final int REQUEST_ENABLE_BT = 0;
final int REQUEST_ENABLE_DISCOVERABLE = 1;
//Flags
Boolean discoveryStarted;
Boolean broadcastReceiverEnabled;
public static synchronized BTHelper getInstance(Activity activity) {
if (sInstance == null) {
sInstance = new BTHelper(activity);
Log.d(TAG, "New BTHelper created");
}
return sInstance;
}
private BTHelper(Activity activity) {
this.mainActivity = activity;
this.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
this.discoveryStarted = false;
this.broadcastReceiverEnabled = false;
}
public BluetoothAdapter getBTAdapter(){
return this.mBluetoothAdapter;
}
public void enableBT(){
if (!mBluetoothAdapter.isEnabled()) {
Log.d(TAG, "enableBT is called");
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
mainActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
public void registerBroadcastReceiver(){
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
mainActivity.registerReceiver(mReceiver, filter);
this.broadcastReceiverEnabled = true;
}
public void unregisterBroadcastReceiver(){
if(this.broadcastReceiverEnabled){
mainActivity.unregisterReceiver(mReceiver);
}
this.broadcastReceiverEnabled = false;
}
public boolean checkBondedDevices(){
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// Loop through paired devices to check for match
for (BluetoothDevice device : pairedDevices) {
//conditions here to find a specific device and connect to it
return true;
}
}
}
return false;
}
public void enableDiscoverable(){
//Enable discoverability
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 60);
mainActivity.startActivityForResult(discoverableIntent, REQUEST_ENABLE_DISCOVERABLE);
}
public void startDiscovery(){
//Start discovering devices
Log.d(TAG, "Starting discovery...");
this.discoveryStarted = true;
mBluetoothAdapter.startDiscovery();
}
// Create a BroadcastReceiver for bluetooth ACTION_FOUND
public final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//Check for matching device
if(check device name/MAC address of specific device){
//Stop discovery
discoveryStarted = false;
mBluetoothAdapter.cancelDiscovery();
//Connect to device here
}
}
}
};
}
您的 BTHelper
class 是一个 Singleton
,这意味着在应用程序运行期间只有一个实例可用。
所以在您的 getInstance()
方法中,您将 Activity
传递给它。第一次使用 activity 初始化它。 activity 完成,登录后 "new" MainActivity 启动。它再次调用 BTHelper.getInstance(this)
。这次它看到 sInstance
不为空(因为 sInstance
是静态的并且之前已设置),因此它返回 sInstance
,其中包含对先前 main [=33= 的先前引用] 现在可能已经被销毁了。实际上,在 Singleton
classes 中使用许可 getInstance
是非常糟糕的做法。您有一份 BTHelper
,但您想将它与不同的 main activity 实例一起使用。所以最好有一个字段 activity 并在每次要使用 BTHelper
时设置,如下所示:
btHelper = BTHelper.getInstance();
btHelper.setCallingActivity(this);
您还应该阅读 Singleton Design Pattern(如果需要的话;))
我有一个应用 LoginActivity
-> MainActivity
。 Main activity 是这样启动的,因为我不想将 LoginActivity
添加到堆栈中:
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
启动 MainActivity
后,在 onResume
中,我检查蓝牙是否已启用。如果没有,请询问用户是否要启用它(这发生在助手 class btHelper
):
public void enableBT(){
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
mainActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
所以在这里,我需要检查用户选择的内容。如果他们选择是,那么我将启用 BT 并注册一个广播接收器。如果他们选择否,我想完成 MainActivity
并返回 LoginActivity
:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == btHelper.REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
//Register broadcast receiver once BT is enabled
btHelper.registerBroadcastReceiver();
} else {
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finishAffinity();
}
}
}
当我 运行 应用程序时,如果用户选择是,则一切正常。如果他们选择“否”,那么一切正常,他们将进入“登录”屏幕。然而,当他们再次登录时,当然会出现对话框询问他们是否要启用 BT,但是如果他们第二次选择否,那么他们就不会被带到登录 - 对话框只是重新显示
我看过这个问题 here 但它似乎不适用,因为我没有以编程方式设置任何结果。出于某种原因,用户选择 No/Deny 只会在第一次时得到正确检查,而在第二次
时则不会考虑到当我单击 No/Deny 时对话框再次显示,我想也许 onResume()
被再次调用从而调用 enableBT()
?我不确定问题是否出在类似问题上或我处理活动之间转换的方式
编辑:
我已经缩小了问题范围。每当调用 onActivityResult
时,我添加了一行以注销 resultCode
值。在第一个 运行 期间,resultCode
得到正确显示,但在重新启动 MainActivity
后的第二个 运行 上,没有任何代码被记录。通过更多测试,似乎在第二次 运行 每当我点击 No/Deny 时,就会调用 enableBT
/onResume
而不是首先检查结果代码以确定它应该是什么做 - 它只是自动重新启动 activity/fragment。这是否意味着 onActivityResult
没有被调用或没有结果代码?
EDIT2:下面添加了完整代码...
登录活动:
public class LoginActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Check if this is a fresh app launch, or a launcher click after app minimize
if (!isTaskRoot()
&& getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
finish();
return;
}
setContentView(R.layout.activity_login);
coordinatorLayoutView = findViewById(R.id.coordinator_layout_login);
//get views for textboxes and buttons
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//perform some password checking, then login
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
}
}
主要活动:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get fragment manager
fragmentManager = getSupportFragmentManager();
//Start the initial fragment
connectFragment = new ConnectFragment();
addFragment(connectFragment, false);
//Set navigation drawer/menu here
//Create bluetooth helper
btHelper = BTHelper.getInstance(this);
}
@Override
protected void onResume(){
super.onResume();
//Check and enable bluetooth
if (btHelper.getBTAdapter() == null) {
//Show alert here saying bluetooth is required, when OK is pressed, invoke `quitToLogin()`
} else {
//If bluetooth is not enabled, ask to enable it
btHelper.enableBT();
}
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy called");
super.onDestroy();
btHelper.unregisterBroadcastReceiver();
}
public void addFragment(Fragment fragment, Boolean addToBackStack) {
if (fragment != null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//Check getFragments() == null to prevent the initial blank
//fragment (before 'Connect' fragment is displayed) from being added to the backstack
if (fragmentManager.getFragments() == null || !addToBackStack) {
fragmentTransaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName())
.commit();
} else {
fragmentTransaction.replace(R.id.fragment_container, fragment, fragment.getClass().getSimpleName())
.addToBackStack(null)
.commit();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "Result code: " + Integer.toString(resultCode));
if (requestCode == btHelper.REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
//Register broadcast receiver once BT is enabled
btHelper.registerBroadcastReceiver();
} else {
quitToLogin();
}
} else if (requestCode == btHelper.REQUEST_ENABLE_DISCOVERABLE) {
if (resultCode == 60) { //result code is discoverable time set in helper
//Start discovery
btHelper.startDiscovery();
} else {
//do other things
}
}
}
public void quitToLogin(){
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finishAffinity();
}
}
BTHelper:
public class BTHelper {
public static final String TAG = "BTHelper";
private static BTHelper sInstance;
Activity mainActivity;
private BluetoothAdapter mBluetoothAdapter;
final int REQUEST_ENABLE_BT = 0;
final int REQUEST_ENABLE_DISCOVERABLE = 1;
//Flags
Boolean discoveryStarted;
Boolean broadcastReceiverEnabled;
public static synchronized BTHelper getInstance(Activity activity) {
if (sInstance == null) {
sInstance = new BTHelper(activity);
Log.d(TAG, "New BTHelper created");
}
return sInstance;
}
private BTHelper(Activity activity) {
this.mainActivity = activity;
this.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
this.discoveryStarted = false;
this.broadcastReceiverEnabled = false;
}
public BluetoothAdapter getBTAdapter(){
return this.mBluetoothAdapter;
}
public void enableBT(){
if (!mBluetoothAdapter.isEnabled()) {
Log.d(TAG, "enableBT is called");
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
mainActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
public void registerBroadcastReceiver(){
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
mainActivity.registerReceiver(mReceiver, filter);
this.broadcastReceiverEnabled = true;
}
public void unregisterBroadcastReceiver(){
if(this.broadcastReceiverEnabled){
mainActivity.unregisterReceiver(mReceiver);
}
this.broadcastReceiverEnabled = false;
}
public boolean checkBondedDevices(){
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// Loop through paired devices to check for match
for (BluetoothDevice device : pairedDevices) {
//conditions here to find a specific device and connect to it
return true;
}
}
}
return false;
}
public void enableDiscoverable(){
//Enable discoverability
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 60);
mainActivity.startActivityForResult(discoverableIntent, REQUEST_ENABLE_DISCOVERABLE);
}
public void startDiscovery(){
//Start discovering devices
Log.d(TAG, "Starting discovery...");
this.discoveryStarted = true;
mBluetoothAdapter.startDiscovery();
}
// Create a BroadcastReceiver for bluetooth ACTION_FOUND
public final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//Check for matching device
if(check device name/MAC address of specific device){
//Stop discovery
discoveryStarted = false;
mBluetoothAdapter.cancelDiscovery();
//Connect to device here
}
}
}
};
}
您的 BTHelper
class 是一个 Singleton
,这意味着在应用程序运行期间只有一个实例可用。
所以在您的 getInstance()
方法中,您将 Activity
传递给它。第一次使用 activity 初始化它。 activity 完成,登录后 "new" MainActivity 启动。它再次调用 BTHelper.getInstance(this)
。这次它看到 sInstance
不为空(因为 sInstance
是静态的并且之前已设置),因此它返回 sInstance
,其中包含对先前 main [=33= 的先前引用] 现在可能已经被销毁了。实际上,在 Singleton
classes 中使用许可 getInstance
是非常糟糕的做法。您有一份 BTHelper
,但您想将它与不同的 main activity 实例一起使用。所以最好有一个字段 activity 并在每次要使用 BTHelper
时设置,如下所示:
btHelper = BTHelper.getInstance();
btHelper.setCallingActivity(this);
您还应该阅读 Singleton Design Pattern(如果需要的话;))