Creator

Creator

By debbuging after @RequiresBluetoothLocationPermission annotation program will exit function startScan in BluetoothLeScanner object

Could you please help me to find the problem why startScan function is not executed. By debugging after @RequiresBluetoothLocationPermission program will not go the next line.

My phone is Samsung Galaxy S22 Ultra Anfroid14, Compile Target SDK 34
Location, Connect, Scan - Permissions will be grandet at Run time This is a function that should be executed with provided ScanCallback

@RequiresLegacyBluetoothAdminPermission
@RequiresBluetoothScanPermission
**@RequiresBluetoothLocationPermission**
@RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
public void startScan(final ScanCallback callback) {
    startScan(null, new ScanSettings.Builder().build(), callback);
}

My program Code:

package com.example.navigationleftexample.ui.gallery;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;


import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.ListFragment;
import androidx.lifecycle.ViewModelProvider;

import android.os.*;

import com.example.navigationleftexample.MainActivity;
import com.example.navigationleftexample.R;
import com.example.navigationleftexample.databinding.FragmentBluetoothBinding;
import com.example.navigationleftexample.ui.Bluetooth.LeDeviceListAdapter;

import pub.devrel.easypermissions.EasyPermissions;


public class BluetoothFragment extends Fragment {
Switch bluetoothSwitch;
private FragmentBluetoothBinding binding;
private BluetoothAdapter mBluetoothAdapter;

private LayoutInflater layoutInflater;
private BluetoothLeScanner bluetoothLeScanner;


private boolean scanning;
private Handler handler = new Handler();

public static final String[] BLUETOOTH_PERMISSIONS_S = 
{ Manifest.permission.BLUETOOTH_SCAN,     Manifest.permission.BLUETOOTH_CONNECT} ;


private static final int PERMISSION_REQUEST_COARSE_LOCATION = 456;

private static final int REQUEST_CODE_BLUETOOTH_SCAN = 1;

// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;



//LeDeviceListAdapter leDeviceListAdapter = new LeDeviceListAdapter(layoutInflater);
LeDeviceListAdapter leDeviceListAdapter;



private boolean checkPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        int permission = ContextCompat.checkSelfPermission
 (getContext(),   Manifest.permission.ACCESS_FINE_LOCATION);
        return permission == PackageManager.PERMISSION_GRANTED;
    }else{
        return true;
    }
}
            // Device scan callback.
private ScanCallback leScanCallback =
        new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
                super.onScanResult(callbackType, result);
                leDeviceListAdapter.addDevice(result.getDevice());
                leDeviceListAdapter.notifyDataSetChanged();
            }
        };


private void scanLeDevice() {
    if (!scanning) {
        // Stops scanning after a predefined scan period.
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                scanning = false;
                if (ActivityCompat.checkSelfPermission(getContext(),
         Manifest.permission.BLUETOOTH_SCAN) 
!= PackageManager.PERMISSION_GRANTED) {
                    // TODO: Consider calling
                    //    ActivityCompat#requestPermissions
                    // 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;
                }
                bluetoothLeScanner.stopScan(leScanCallback);
            }
        }, SCAN_PERIOD);

        scanning = true;
        bluetoothLeScanner.startScan(leScanCallback);
    } else {
        scanning = false;
        //bluetoothLeScanner.stopScan(leScanCallback);
        scanLeDevice();
    }
}




public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
    BluetoothViewModel bluetoothViewModel =
            new ViewModelProvider(this).get(BluetoothViewModel.class);


    // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
    // BluetoothAdapter through BluetoothManager.
    final BluetoothManager bluetoothManager =
            (BluetoothManager) getContext().getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();




    // Checks if Bluetooth is supported on the device.
    if (mBluetoothAdapter == null) {
        Toast.makeText(getContext(), R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
        getActivity().finish();

    }
    bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();

    layoutInflater = inflater;

    binding = FragmentBluetoothBinding.inflate(inflater, container, false);
    View root = binding.getRoot();


    // Check Bluetooth Switch
    bluetoothSwitch = (Switch) binding.switchBluetoothOn;
    bluetoothSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            Toast.makeText(root.getContext(), "Bluetooth was changed", Toast.LENGTH_SHORT).show();
            if (isChecked==true)
            {

                // Use this check to determine whether BLE is supported on the device.  Then you can
                // selectively disable BLE-related features.
                if   (!getActivity().getPackageManager().
hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                    Toast.makeText(getContext(), 
R.string.ble_not_supported,   Toast.LENGTH_SHORT).show();
                    getActivity().finish();
                }


                //  Check permissions for Bluetooth Connect
                if (ContextCompat.checkSelfPermission(getContext(), 
 Manifest.permission.BLUETOOTH_CONNECT) 
 == PackageManager.PERMISSION_DENIED)
                {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
                    {
                        ActivityCompat.requestPermissions(getActivity(), 
new String[] {Manifest.permission.BLUETOOTH_CONNECT}, 2);
                        return;
                    }
                }
                // Request Scan permission
                ActivityCompat.requestPermissions(getActivity(), 
new String[] 
{Manifest.permission.BLUETOOTH_SCAN}, REQUEST_CODE_BLUETOOTH_SCAN);



                boolean fineLocation = checkPermission();


                leDeviceListAdapter = new LeDeviceListAdapter(layoutInflater);
                scanLeDevice();
            }
            else
            {
                leDeviceListAdapter.clear();
                //scanLeDevice(false);
            }
        }
    });

    //  Show Connected Bluetooth Device
    final TextView textView = binding.textViewBluetoothDeviceChosen;
    bluetoothViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);

    // Show List of Bluetooth scanned devices
    final ListView listView = (ListView) binding.listBluetoothDeviceView;
    //String [] deviceArray = bluetoothViewModel.getDeviceArray();





    listView.setAdapter(leDeviceListAdapter);

    // Create Listener for the List
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final String item = (String) parent.getItemAtPosition(position);
            Toast.makeText(root.getContext(), "You have selected item: " + item,  
  Toast.LENGTH_SHORT).show();


        }
    });



    return root;
}

@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    ActivityResultLauncher<String[]> locationPermissionRequest =
            registerForActivityResult(new ActivityResultContracts
                            .RequestMultiplePermissions(), result -> {
                        Boolean fineLocationGranted = result.getOrDefault(
                                Manifest.permission.ACCESS_FINE_LOCATION, false);
                        Boolean coarseLocationGranted = result.getOrDefault(
                                Manifest.permission.ACCESS_COARSE_LOCATION,false);
                        if (fineLocationGranted != null && fineLocationGranted) {
                            // Precise location access granted.
                            Toast.makeText(getContext(), "Precise location granted" ,  
 Toast.LENGTH_SHORT).show();
                        } else if (coarseLocationGranted != null && coarseLocationGranted) {
                            // Only approximate location access granted.
                            Toast.makeText(getContext(), "Aproximate location granted" , 
 Toast.LENGTH_SHORT).show();
                        } else {
                            // No location access granted.
                            Toast.makeText(getContext(), "No location granted" , 
 Toast.LENGTH_SHORT).show();
                        }
                    }
            );

    locationPermissionRequest.launch(new String[] {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    });
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    binding = null;
}


}

Permissions from Android manifest:

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


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



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

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


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



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

<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />


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

<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BILLING" />

Most Liked

Creator

Creator

Code is working fine. I have not initialized leDeviceListAdapter befor i set it to ListView

Where Next?

Popular Android topics Top

husaindevelop
Inside our android webview app, we are trying to paste the copied content from another app eg (notes) using navigator.clipboard.readtext ...
New
cve60069
Hello I am starting the tearning curve to writing an app for my galaxy phone. Me and my friens play a lot of “Texas Hold-Em” and, for t...
New
tunelabguy
I have an expensive app ($160) in the Play Store that I would like to update. I would like to do a beta test of the update with potentia...
New
Briannamari
Old android photo name sequence Help decoding file names Example. I want to see if a file name aligns with a time / date in which the p...
New
Creator
Could you please help me to find the problem why startScan function is not executed. By debugging after @RequiresBluetoothLocationPermiss...
New
hasan10242048
There is an Android app. I just want to create two GRAPHS with CPU Runtime and Battery Consumption. It is as simple as this. I tried w...
New
AnfaengerAlex
Hello, I’m a beginner in Android development and I’m facing an issue with my project setup. In my build.gradle.kts file, I have the foll...
New
Garrett
This is a question about Android Studio. Where is the Android Studio emulator’s camera default apartment 3D model stored in Android Stud...
New
Garrett
I’m stuck trying to understand how to get a variable initialised, and later updated, in kotlin to update in Jetpack Compose and cause a c...
New
Alan
I need to create an android app to receive contactless payment from my clients. how can I start that? My clients will be phisicaly in the...
New

Other popular topics Top

PragmaticBookshelf
Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell. With Seven Languages in Seven Weeks, by Bruce A. Tate, you’ll go beyond the syntax—and...
New
PragmaticBookshelf
Write Elixir tests that you can be proud of. Dive into Elixir’s test philosophy and gain mastery over the terminology and concepts that u...
New
ohm
Which, if any, games do you play? On what platform? I just bought (and completed) Minecraft Dungeons for my Nintendo Switch. Other than ...
New
New
PragmaticBookshelf
Rust is an exciting new programming language combining the power of C with memory safety, fearless concurrency, and productivity boosters...
New
AstonJ
Just done a fresh install of macOS Big Sur and on installing Erlang I am getting: asdf install erlang 23.1.2 Configure failed. checking ...
New
AstonJ
If you are experiencing Rails console using 100% CPU on your dev machine, then updating your development and test gems might fix the issu...
New
AstonJ
If you get Can't find emacs in your PATH when trying to install Doom Emacs on your Mac you… just… need to install Emacs first! :lol: bre...
New
AstonJ
This is a very quick guide, you just need to: Download LM Studio: https://lmstudio.ai/ Click on search Type DeepSeek, then select the o...
New
RobertRichards
Hair Salon Games for Girls Fun Girls Hair Saloon game is mainly developed for kids. This game allows users to select virtual avatars to ...
New