Android: Set Bluetooth Discoverability Unbounded

2019-02-15 18:20发布

问题:

I have spent the last couple of days trying to make an app that keeps my Samsung Galaxy S3 mini (Android 2.1.4) discoverable for an "infinite" amount of time. My code looks currently as follows:

package com.example.downtoone;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;

import com.example.downtoone.*;
import android.bluetooth.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

public class MainActivity extends Activity {

    private BluetoothAdapter mBluetoothAdapter = null;

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE = 1;
    private static final int REQUEST_ENABLE_BT = 2;
    private static final int REQUEST_ENABLE_DSC = 3;

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

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
    }   
    @Override
    public void onStart() {
        super.onStart();

        if (!mBluetoothAdapter.isEnabled()) {
            Intent MDisc = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            MDisc.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,0);
            startActivityForResult(MDisc, REQUEST_ENABLE_DSC);
        }
    }
    @Override
    public void onRestart(){
        super.onRestart();
    }
    @Override
    public void onResume() {
        super.onResume();
    }
    @Override
    public void onStop() {
        super.onStop();
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case REQUEST_CONNECT_DEVICE:
            if (resultCode == Activity.RESULT_OK) {

            }
            break;
        case REQUEST_ENABLE_BT:
            if (resultCode == Activity.RESULT_CANCELED) {
                Toast.makeText(this, "BLUETOOTH NEEDS TO BE ENABLED AND DISCOVERABLE", Toast.LENGTH_SHORT).show();
                finish();
            }
            break;
        case REQUEST_ENABLE_DSC:
            if (resultCode == Activity.RESULT_CANCELED) {
                Toast.makeText(this, "BLUETOOTH NEEDS TO BE ENABLED AND DISCOVERABLE", Toast.LENGTH_SHORT).show();
                //finish();
            }
            break;
        }
    }

    public void finishBTsetup(){

    }
}

Despite the fact that I am setting the time to '0', discoverability only runs for 2minutes. This is rather frustrating since I know the device can handle to be discoverable for an indefinite amount of time! ( I could manually access the bluetooth settings and set Bluetooth Visibility to 'Never Time Out'!)

I've looked all over for an answer without success... many posts give what (for a relative unskilled programmer such as me) look like arcane solutions that are either too vague(*), confusing(**) or downright wrong. A simple straightforward answer solving this issue (if it exists of course!) would be greatly appreciated!

(*) Make Bluetooth on Android 2.1 discoverable indefinitely

(**) Extend Android Bluetooth Discoverability Android Application Bluetooth visibility duration (answer section)

MANIFEST:

<?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.downtoone"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="14"
            android:targetSdkVersion="14" />
        <uses-permission android:name="android.permission.BLUETOOTH"/>
        <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />  
        <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />


        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

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

    </manifest>

EDIT: To give people a little context, one of the goals of this application is to try and be DISCOVERABLE to all nearby Bluetooth devices so that it can directly talk to them. Since most smartphones are discoverable for short amounts of time (2min usually*) and only so when the user directly enables discoverability (= visibility), apps that scan for devices and automatically exchange data are impossible to implement. (* The user can usually set the visibility to 'No Time Out', but that requires the user to set that option directly under Bluetooth Settings of their smartphone, which is not a very elegant solution...)

回答1:

I come to the same conclusion on three devices I have.

  • ANDROID v 4.3 and higher : EXTRA_DISCOVERABLE_DURATION 0 works no limit
  • ANDROIND v 4.1 : EXTRA_DISCOVERABLE_DURATION 0 is max 1 hour. Have to change manually to no limit in parameters.


回答2:

above api level 14 EXTRA_DISCOVERABLE_DURATION 0 works with infinite limit but below this it works for max 1 hour.

This code works for me

Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 0);
startActivityForResult(intent, Utils.REQUEST_DEVICE_DISCOVERABLE);


回答3:

According to Android documentation, the maximum time for being discoverable is capped at 300seconds. You cannot make the BT discoverable forever.

Please see: http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#ACTION_REQUEST_DISCOVERABLE

In order to get the 300second maximum period, you need to change one line of code as:

MDisc.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300)


回答4:

Im not sure if this would suit your application or if theres some other reason why you don't want to do this but why not just discover for the default time then restart discovery when it times out? this way it will technically be an unlimited discovery, which will only trigger a VERY slight pause in between, I used this method in my application using a broadcast receiver.

I put startDiscovery() in the onStart() method to trigger discovery on activity start, then listen to ACTION_DISCOVERY_FINISHED in your broadcast receiver's onReceive() method, here place another call to startDiscovery().

this will loop the discovery forever, if you want to stop when you find a device then call cancelDiscovery() in you receiver's ACTION_FOUND listener, you can also place some checking here if you need to find a particular device - again in my case i was checking for a particular device's mac address so the discovery would continue until this was found.

not sure if this is any use but if you need more detail let me know.



回答5:

I've arrived to the conclusion that it can't be done, unless the user goes to Bluetooth > Settings > Visibility timeout and sets the timeout accordingly.

Peace.



回答6:

Works to me.

Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
enableBtIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 0);
startActivityForResult(enableBtIntent, Utils.REQUEST_DEVICE_DISCOVERABLE);

Disable manually your Bluetooth and then run the code. It will works, yes.