2

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...)

Community
  • 1
  • 1
MrRed
  • 719
  • 3
  • 9
  • 20

6 Answers6

2

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.
Frederic J.
  • 44
  • 1
  • 3
1

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);
Amit Pathak
  • 186
  • 3
0

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)
Kasra
  • 3,045
  • 3
  • 17
  • 34
  • "By default, the device will become discoverable for 120 seconds. You can define a different duration by adding the EXTRA_DISCOVERABLE_DURATION Intent extra. The maximum duration an app can set is 3600 seconds, and a value of 0 means the device is always discoverable." (http://developer.android.com/guide/topics/connectivity/bluetooth.html#DiscoveringDevices) – MrRed Jan 20 '15 at 05:38
  • ^The quote is found under "Enabling Discoverability" – MrRed Jan 20 '15 at 05:46
  • Alright... Another inconsistency in documentation... Looks like they added the infinite duration in Android 4.0. Change your Manifest file and set the minimum and target sdk version to "14". Let me know if it works – Kasra Jan 20 '15 at 18:35
  • I changed it to 14 for both values and still not working :/ The more I search the more it seems that it might actually be impossible to do... – MrRed Jan 20 '15 at 20:21
  • I ran two tests. One is in an old OPPO phone (android 5.1), seems the infinite discovery setting is working. I even cannot reset after turning off and on the phone. It seems it is going to be discoverable forever. No idea. Another test is in Galaxy 7 (android 8.0). It pops up the dialogue saying it will become discoverable for 120s. The discoverable mode becomes over at 120 seconds. Yes, it is another inconsistency in the documentation. – Freddie Apr 26 '20 at 00:36
0

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.

user3812950
  • 37
  • 1
  • 6
  • 1
    Thank you, but I don't think your solution applies to my problem. You are talking about keeping my application in Discovering Mode for infinite amount of time, which means it is searching for Discoverable devices indefinitely. But how did those devices become discoverable in the first place? Aha! Well, because their own BluetoothAdapters were set to Discoverable mode! See the difference? Discovering mode = Looking for other devices that ARE discoverable; Discoverable mode = Being perceptible by other devices that are scanning. So, all I care about is always being in discoverable mode – MrRed Jan 24 '15 at 15:42
0

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.

MrRed
  • 719
  • 3
  • 9
  • 20
0

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.

  • Well, if you look at the onStart method from my code it looks exactly the same as your code. Are you sure it ran indefinitely? **Try putting your Bluetooth Settings to Visibility Timeout 2min**. Then turn off the bluetooth. Then run your code and see if the bluetooth is visible for **more than** 2min. If it doesnt work then you have the same problem as me – MrRed Jan 31 '15 at 22:15
  • I did two tests: First, I enabled the BT and put timeout visibility to 2 min. After 2 minutes it was gone. Second, I run my app and then it is visible until now, more than 10 minutes. My android is 4.4.4. Maybe that can influence. – Jean Hansen Feb 01 '15 at 14:41
  • Thanks for checking, I figured that your Android version would be higher than mine :/ – MrRed Feb 01 '15 at 16:58
  • Independent of your Android version, put your targetVersion to higher, in AndroidManifest. Maybe this can help you. – Jean Hansen Feb 01 '15 at 19:08
  • I just modified my Manifest to have ' ' but the discoverability disappears right after 2 minutes even though I set to a duration of 0 (i.e. infinite time). The only logical explanation is that the ability to set unbounded discoverability is only possible on devices with Android 4.4 or higher.. Thanks Jean – MrRed Feb 04 '15 at 02:38