3

I would like grant access to Enable and Disable Bluetooth from Android Studio. I also pretend to use other functionalities of Bluetooth as list of devices and connect to previous pared device and more.

Since starActivityForResult has been Deprecated, I'm having trouble to lunch the pop up activity that ask the user for allowance.

This is my manifest

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.bluetoothonofftest"
    tools:ignore="CoarseFineLocation">

    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30"
        tools:ignore="CoarseFineLocation" />

    <!-- Needed only if your app looks for Bluetooth devices.
         If your app doesn't use Bluetooth scan results to derive physical
         location information, you can strongly assert that your app
         doesn't derive physical location. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

    <uses-feature android:name="android.hardware.bluetooth" android:required="true"/>

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.BlUetoothTest">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>   

This is my ManinActivity

package com.example.bluetoothexamples;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Set;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int REQUEST_ENABLE_BT = 0;
    private static final int REQUEST_DISCOVER_BT = 1;

    TextView mStatusBlueTv;
    TextView mPairedTv;

    ImageView mBlueIv;

    Button mOnBtn;
    Button mOffBtn;
    Button mDiscoverBtn;
    Button mPairedBtn;

    BluetoothAdapter mBlueAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mStatusBlueTv = findViewById(R.id.statusBluetoothTv);
        mPairedTv = findViewById(R.id.pairedTv);

        mBlueIv = findViewById(R.id.bluetoothIv);

        mOnBtn = findViewById(R.id.onBtn);
        mOffBtn = findViewById(R.id.offBtn);
        mDiscoverBtn = findViewById(R.id.discoverableBtn);
        mPairedBtn = findViewById(R.id.pairedBtn);

        // Adapter
        mBlueAdapter = BluetoothAdapter.getDefaultAdapter();

        //Check if bluetooth is available or not
        if (mBlueAdapter == null) {
            mStatusBlueTv.setText("Bluetooth is NOT Available");
        } else {
            mStatusBlueTv.setText("Bluetooth is Available");

            // Set image according to bluetooth status (on/off)
            if (mBlueAdapter.isEnabled()) {
                mBlueIv.setImageResource(R.drawable.ic_action_on);
            } else {
                mBlueIv.setImageResource(R.drawable.ic_action_off);
            }

            mOnBtn.setOnClickListener(this);          // Turn on Bluetooth btn click
            mDiscoverBtn.setOnClickListener(this);    // Discover bluetooth btn click
            mOffBtn.setOnClickListener(this);         // Turn off Bluetooth btn click
            mPairedBtn.setOnClickListener(this);      // Get Paired devices button click
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {

            // Turn on Bluetooth btn click
            case R.id.onBtn:

                if (!mBlueAdapter.isEnabled()) {
                   // showToast("Turning On Bluetooth...");

//                    if (getApplicationContext().checkSelfPermission(Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
//                    } else {
//                        requestPermissions(new String[]{Manifest.permission.BLUETOOTH_ADMIN},1);
//                    }


                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_ADMIN},1);
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        return;
                    }

                    // Intent to On Bluetooth
                    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    startActivityForResult(intent, REQUEST_ENABLE_BT);
                }
                else {
                    showToast("Bluetooth is already on");
                }

            break;

            // Discover bluetooth btn click
            case R.id.discoverableBtn:

                if (!mBlueAdapter.isDiscovering()){
                    showToast("Making Your Device Discoverable");
                    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                    startActivityForResult(intent ,REQUEST_DISCOVER_BT);
                }

            break;

            // Turn off Bluetooth btn click
            case R.id.offBtn:

                if (mBlueAdapter.isEnabled()) {
                    mBlueAdapter.disable();
                    showToast("Turning Bluetooth Off");
                    mBlueIv.setImageResource(R.drawable.ic_action_off);
                }
                else {
                    showToast("Bluetooth is already off");
                }

             break;
                // Get Paired devices button click
            case R.id.pairedBtn:

                if (mBlueAdapter.isEnabled()) {
                    mPairedTv.setText("Paired Devices");
                    Set<BluetoothDevice> devices = mBlueAdapter.getBondedDevices();
                    for (BluetoothDevice device: devices){
                        mPairedTv.append("\nDevice: " + device.getName() + ", " + device);
                    }
                }
                else {
                    //bluetooth is off so can't get paired devices
                    showToast("Turn ON Bluetooth to get paired devices");
                }

                break;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 1){
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                showToast("Permission Granted");
            }
            else {
                showToast("Permission Denied");
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch (requestCode){
            case REQUEST_ENABLE_BT:

                if (resultCode == RESULT_OK) {
                    // Bluetooth is on
                    mBlueIv.setImageResource(R.drawable.ic_action_on);
                    showToast("Bluetooth is on");
                }
                else {
                    showToast("Failed to connect to bluetooth");
                }

            break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    //Toast message function
    private void showToast (String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }
}

This is my XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context=".MainActivity">

<!--    Display whether bluetooth is available or not-->
    <TextView
        android:id="@+id/statusBluetoothTv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text=""
        android:textAlignment="center"
        android:textSize="20sp"
        android:textColor="#000" />

<!--    Bluetooth icon-->
    <ImageView
        android:id="@+id/bluetoothIv"
        android:layout_width="100dp"
        android:layout_height="100dp" />

<!--    on Button-->
    <Button
        android:id="@+id/onBtn"
        android:minWidth="200dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Turn On"
        style="@style/Base.Widget.AppCompat.Button.Colored" />

<!--    off Button-->
    <Button
        android:id="@+id/offBtn"
        android:minWidth="200dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Turn Off"
        style="@style/Base.Widget.AppCompat.Button.Colored" />

<!--    Discoverable button-->
    <Button
        android:id="@+id/discoverableBtn"
        android:minWidth="200dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Discoverable"
        style="@style/Base.Widget.AppCompat.Button.Colored" />

<!--    Get list of paired devices button-->
    <Button
        android:id="@+id/pairedBtn"
        android:minWidth="200dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get Paired Devices"
        style="@style/Base.Widget.AppCompat.Button.Colored" />

<!--    Show paired devices here-->
    <TextView
        android:id="@+id/pairedTv"
        android:minWidth="200dp"
        android:text=""
        android:textColor="#000"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

1 Answers1

8

Currently the recommended approach is using a ActivityResultLauncher to get the results like so:

ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
             if (result.getResultCode() == Activity.RESULT_OK) {
                 Log.e("Activity result","OK");
                 // There are no request codes
                Intent data = result.getData();
            }
        });

so just call it like:

Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        activityResultLauncher.launch(intent);

and for your case assuming everything else is working fine ,you update to something like below:

package com.example.bluetoothexamples;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import android.app.Activity;
import android.util.Log;

import java.util.Set;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int REQUEST_ENABLE_BT = 0;
    private static final int REQUEST_DISCOVER_BT = 1;

    TextView mStatusBlueTv;
    TextView mPairedTv;

    ImageView mBlueIv;

    Button mOnBtn;
    Button mOffBtn;
    Button mDiscoverBtn;
    Button mPairedBtn;

    BluetoothAdapter mBlueAdapter;
ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                 if (result.getResultCode() == Activity.RESULT_OK) {
                     Log.e("Activity result","OK");
                     // There are no request codes
                    Intent data = result.getData();
                }
            });
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mStatusBlueTv = findViewById(R.id.statusBluetoothTv);
        mPairedTv = findViewById(R.id.pairedTv);

        mBlueIv = findViewById(R.id.bluetoothIv);

        mOnBtn = findViewById(R.id.onBtn);
        mOffBtn = findViewById(R.id.offBtn);
        mDiscoverBtn = findViewById(R.id.discoverableBtn);
        mPairedBtn = findViewById(R.id.pairedBtn);

        // Adapter
        mBlueAdapter = BluetoothAdapter.getDefaultAdapter();

        //Check if bluetooth is available or not
        if (mBlueAdapter == null) {
            mStatusBlueTv.setText("Bluetooth is NOT Available");
        } else {
            mStatusBlueTv.setText("Bluetooth is Available");

            // Set image according to bluetooth status (on/off)
            if (mBlueAdapter.isEnabled()) {
                mBlueIv.setImageResource(R.drawable.ic_action_on);
            } else {
                mBlueIv.setImageResource(R.drawable.ic_action_off);
            }

            mOnBtn.setOnClickListener(this);          // Turn on Bluetooth btn click
            mDiscoverBtn.setOnClickListener(this);    // Discover bluetooth btn click
            mOffBtn.setOnClickListener(this);         // Turn off Bluetooth btn click
            mPairedBtn.setOnClickListener(this);      // Get Paired devices button click
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {

            // Turn on Bluetooth btn click
            case R.id.onBtn:

                if (!mBlueAdapter.isEnabled()) {
                   // showToast("Turning On Bluetooth...");

//                    if (getApplicationContext().checkSelfPermission(Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
//                    } else {
//                        requestPermissions(new String[]{Manifest.permission.BLUETOOTH_ADMIN},1);
//                    }


                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_ADMIN},1);
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        return;
                    }

                    // Intent to On Bluetooth
                    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                  //  startActivityForResult(intent, REQUEST_ENABLE_BT);
                      
        activityResultLauncher.launch(intent);
                }
                else {
                    showToast("Bluetooth is already on");
                }

            break;

            // Discover bluetooth btn click
            case R.id.discoverableBtn:

                if (!mBlueAdapter.isDiscovering()){
                    showToast("Making Your Device Discoverable");
                    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                    //startActivityForResult(intent ,REQUEST_DISCOVER_BT);
                     activityResultLauncher.launch(intent);
                }

            break;

            // Turn off Bluetooth btn click
            case R.id.offBtn:

                if (mBlueAdapter.isEnabled()) {
                    mBlueAdapter.disable();
                    showToast("Turning Bluetooth Off");
                    mBlueIv.setImageResource(R.drawable.ic_action_off);
                }
                else {
                    showToast("Bluetooth is already off");
                }

             break;
                // Get Paired devices button click
            case R.id.pairedBtn:

                if (mBlueAdapter.isEnabled()) {
                    mPairedTv.setText("Paired Devices");
                    Set<BluetoothDevice> devices = mBlueAdapter.getBondedDevices();
                    for (BluetoothDevice device: devices){
                        mPairedTv.append("\nDevice: " + device.getName() + ", " + device);
                    }
                }
                else {
                    //bluetooth is off so can't get paired devices
                    showToast("Turn ON Bluetooth to get paired devices");
                }

                break;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 1){
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                showToast("Permission Granted");
            }
            else {
                showToast("Permission Denied");
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch (requestCode){
            case REQUEST_ENABLE_BT:

                if (resultCode == RESULT_OK) {
                    // Bluetooth is on
                    mBlueIv.setImageResource(R.drawable.ic_action_on);
                    showToast("Bluetooth is on");
                }
                else {
                    showToast("Failed to connect to bluetooth");
                }

            break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    //Toast message function
    private void showToast (String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }
}

for java <8 :

   ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
                @Override
                public void onActivityResult(ActivityResult result) {
                    if (result.getResultCode() == Activity.RESULT_OK) {
                        Log.e("Activity result", "OK");
                        // There are no request codes
                        Intent data = result.getData();
                    }
                }
            }
            );
Daniel Lord
  • 754
  • 5
  • 18
Code Demon
  • 1,256
  • 1
  • 9
  • 15
  • Thank you so much, I was able to tested and the problem is solve. Your answer help me a lot. have a great day!!! – Adrian Suarez del Villar Feb 08 '22 at 14:39
  • Isn't the sistem dialog automatically shown when the component is resumed? I'm having some issues with this approach as it triggers the flow each time my fragment is getting resumed. – Ionut Negru Jul 31 '23 at 16:58