未检查 Android Activity 结果

标签 android android-intent android-activity android-bluetooth

我有一个应用 LoginActivity -> MainActivity。主要 Activity 是这样开始的,因为我不想将 LoginActivity 添加到堆栈中:

Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();

启动 MainActivity 后,在 onResume 中,我检查蓝牙是否已启用。如果没有,请询​​问用户是否要启用它(这发生在辅助类 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但它似乎不适用,因为我没有以编程方式设置任何结果。出于某种原因,用户选择“否”/“拒绝”只会在第一次时得到正确检查,而第二次则不会

考虑到当我单击“否/拒绝”时对话框再次显示,我想也许 onResume() 被再次调用从而调用 enableBT()?我不确定问题是否与此类似,还是我处理 Activity 之间转换的方式

编辑:

我已经缩小了问题范围。每当调用 onActivityResult 时,我添加了一行以注销 resultCode 值。在第一次运行期间,resultCode 得到正确显示,但在重新启动 MainActivity 后的第二次运行中,没有任何代码被记录。通过更多测试,似乎在第二次运行时,每当我点击否/拒绝时,都会调用 enableBT/onResume 而不是首先检查结果代码以确定它应该做什么做 - 它只是自动重新启动 Activity/fragment 。这是否意味着 onActivityResult 没有被调用或者没有结果代码?

EDIT2:下面添加了完整的代码......

登录 Activity :

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();
            }
        });
    }
}

主要 Activity :

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();
    }
}

BT助手:

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 类是一个 Singleton,这意味着在应用程序运行期间只有一个实例可用。

所以在您的 getInstance() 方法中,您将 Activity 传递给它。第一次使用 Activity 初始化它。 Activity 结束,登录 "new" MainActivity 后启动。它再次调用 BTHelper.getInstance(this)。这次它看到 sInstance 不为空(因为 sInstance 是静态的并且之前已设置),所以它返回保存前一个的 sInstance引用以前的主要 Activity ,现在可能已被销毁。实际上,在 Singleton 类中使用许可的 getInstance 是非常糟糕的做法。您有一个 BTHelper 副本,但您想将它用于主要 Activity 的不同实例。所以每次你想使用 BTHelper 时最好有一个实地 Activity 和设置:

btHelper = BTHelper.getInstance();
btHelper.setCallingActivity(this);

您还应该阅读 Singleton Design Pattern (如果需要的话;))

关于未检查 Android Activity 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37628308/

相关文章:

android - 无法解析 : com. android.support :support-v4:26. 3.1

android - 当应用程序在后台运行时接收Intent(服务应用程序)

Android:在不在缓存文件夹/临时文件中创建副本的情况下从我的应用程序共享大文件(图像、文档等...)

java - 从 ListActivity 条目启动 Intent - Android

android - 同一 View 中的两个 Activity

Android套接字 - 一台服务器多个客户端

java - 如何使用带有 Web 身份验证的 apache httpclient 进行 http 发布?

android - 使用 Android Media Projection API 进行可靠的屏幕捕获

android - 通过 AsyncTask 将值从第一个 Activity 传递到第三个 Activity

java - 如何使取消按钮在 android web View 中链接的 sdk 调用中工作?