I am trying to scan another BLE device, but it is not finding another BLE device.
Instead, it scanned a Bluetooth device with api <18.
This is my code :
package com.example.blescan;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class DeviceScanActivity extends ListActivity {
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle(getString(R.string.app_name));
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device.
// Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT)
.show();
finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a
// reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(this, R.string.error_bluetooth_not_supported,
Toast.LENGTH_SHORT).show();
finish();
return;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (!mScanning) {
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
} else {
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(
R.layout.actionbar_indeterminate_progress);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_scan:
mLeDeviceListAdapter.clear();
scanLeDevice(true);
break;
case R.id.menu_stop:
scanLeDevice(false);
break;
}
return true;
}
#Override
protected void onResume() {
super.onResume();
// Ensures Bluetooth is enabled on the device. If Bluetooth is not
// currently enabled,
// fire an intent to display a dialog asking the user to grant
// permission to enable it.
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT
&& resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
invalidateOptionsMenu();
}
// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflator = DeviceScanActivity.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if (!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflator.inflate(R.layout.listitem_device, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView) view
.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view
.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice device = mLeDevices.get(i);
final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 0)
viewHolder.deviceName.setText(deviceName);
else
viewHolder.deviceName.setText(R.string.unknown_device);
viewHolder.deviceAddress.setText(device.getAddress());
return view;
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
static class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device. This can be
// result of read or notification operations.
}
These are the requested permissions:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Please help me.
Related
I have been trying to do lock task mode or lock into my app without being able to access other apps with still being able to disable the feature. I have looked at tutorials and documentation but some methods were deprecated since they were made around 5 years ago (onActivityResult). I have tried to change to the new methods (registerForActivityResult) that I found, however when I launch my app and try to enable admin permission by tapping on the enable button, the admin permissions don't pop up, so I cannot check it. So, when I try to lock my phone from other apps nothing happens because I don't have admin permissions.My Code for MainActivity.class below:
package com.example.myapplication;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.myapplication.databinding.ActivityMainBinding;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.example.myapplication.helper.MqttHelper;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button lock, disable, enable;
private static final int RESULT_ENABLE = 11;
private DevicePolicyManager devicePolicyManager;
private ActivityManager activityManager;
private ComponentName componentName;
private AppBarConfiguration appBarConfiguration;
private ActivityMainBinding binding;
MqttHelper mqttHelper;
//ChartHelper mChart;
//LineChart chart;
TextView dataReceived;
private Button btnPublish;
// Allowlist two apps.
private static final String KIOSK_PACKAGE = "com.example.myapplication";
private static final String[] APP_PACKAGES = {KIOSK_PACKAGE};
// ...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
//setContentView(R.layout.activity_main);
devicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
componentName = new ComponentName(this, Controller.class);
lock = (Button) findViewById(R.id.lock);
enable = (Button) findViewById(R.id.enable);
disable = (Button) findViewById(R.id.disable);
lock.setOnClickListener(this);
enable.setOnClickListener(this);
disable.setOnClickListener(this);
dataReceived = (TextView) findViewById(R.id.textview_first);
startMqtt();
}
#Override
protected void onResume() {
super.onResume();
boolean isActive = devicePolicyManager.isAdminActive(componentName);
}
#Override
public void onClick(View view) {
if (view == lock) {
boolean active = devicePolicyManager.isAdminActive(componentName);
if(active) {
devicePolicyManager.lockNow();
} else {
Toast.makeText(this, "You need to enable the Admin Device Features", Toast.LENGTH_SHORT).show();
}
} else if (view == enable) {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"You Should Enable the app!");
//someActivityResultLauncher.launch(intent);
// Caller
mGetContent.launch(intent);
// Receiver
//startActivityForResult(intent, RESULT_ENABLE);
} else if (view == disable) {
devicePolicyManager.removeActiveAdmin(componentName);
disable.setVisibility(View.GONE);
enable.setVisibility(View.VISIBLE);
}
}
ActivityResultLauncher<Intent> mGetContent = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
// Here, no request code
Intent data = result.getData();
Toast.makeText(MainActivity.this, "enabled", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this, "Failed", Toast.LENGTH_SHORT).show();
}
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode== Activity.RESULT_OK && requestCode == RESULT_ENABLE){
Toast.makeText(MainActivity.this, "enabled", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "Failed", Toast.LENGTH_SHORT).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
/*#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case RESULT_ENABLE:
if(resultCode== Activity.RESULT_OK ){
//btn_unblock.setText("Dissable");
//btn_block.setVisibility(View.VISIBLE);
Toast.makeText(MainActivity.this, "enabled", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this, "Failed", Toast.LENGTH_SHORT).show();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}*/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}
// MQTT Code
private void startMqtt(){
mqttHelper = new MqttHelper(getApplicationContext());
mqttHelper.mqttAndroidClient.setCallback(new MqttCallbackExtended() {
#Override
public void connectComplete(boolean b, String s) {
Log.w("Debug","Connected");
}
#Override
public void connectionLost(Throwable throwable) {
}
#Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
Log.w("Debug",mqttMessage.toString());
dataReceived.setText(mqttMessage.toString());
//mChart.addEntry(Float.valueOf(mqttMessage.toString()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
});
}
}
I am working on this project where I am supposed to utilize Bluetooth beacons to create an indoor map with direction finding(mobile app). This is how the idea is supposed to go: mobile device interacting with BLE devices through BLE scanner, scanner gets the device information (MAC-address, rssi..etc) So far what I've done is I am able to make the scanner work and I have a map with an indoor floor plan layered.
What I am trying to do now is to integrate the BLE scanner with the map such that the scanner works at the backend automatically scanning and connecting to BLE devices, therefore using the information(specifically RSSI values) to work out the distance between the device and beacon. I am totally lost on what and how to do it as it is my first time developing a mobile application.
Here is the image of the map as stated above.
map with floor plan
So far I have only tried to copy the codes of the BLE scanner into the project of the map but I have no clue how to merge the two such that it gives me the above stated outcome
Here are the codes of the BLE scanner:
DeviceScanActivity.java
package com.example.android.bluetoothlegatt;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
/**
* Activity for scanning and displaying available Bluetooth LE devices.
*/
public class DeviceScanActivity extends ListActivity {
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 123;
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle(R.string.title_devices);
mHandler = new Handler();
//need to be able to access location before can scan
//for when build ver sdk 23+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (!mScanning) {
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
} else {
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(
R.layout.actionbar_indeterminate_progress);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_scan:
mLeDeviceListAdapter.clear();
scanLeDevice(true);
break;
case R.id.menu_stop:
scanLeDevice(false);
break;
}
return true;
}
#Override
protected void onResume() {
super.onResume();
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
// fire an intent to display a dialog asking the user to grant permission to enable it.
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
if (device == null) return;
final Intent intent = new Intent(this, DeviceControlActivity.class);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
if (mScanning) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mScanning = false;
}
startActivity(intent);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
invalidateOptionsMenu();
}
// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflator = DeviceScanActivity.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if(!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflator.inflate(R.layout.listitem_device, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice device = mLeDevices.get(i);
final String deviceName = device.getName();
final String deviceAddress = device.getAddress();
if (deviceName != null && deviceName.length() > 0 && deviceAddress.contains("00:15:88:07"))
viewHolder.deviceName.setText(device.getName());
else
viewHolder.deviceName.setText(R.string.unknown_device);
// viewHolder.deviceAddress.setText(R.string.invalid_address);
viewHolder.deviceAddress.setText(device.getAddress());
return view;
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
static class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
}
I would appreciate if anyone could help me with this problem I have been trying to solve for the past few days. Thank you very much!
I am trying to use Google's Sample BLE library to send data between two LG Phoenix 4 phones, both running Android 7.1 and both BLE-compatible. I have successfully gotten the app onto both phones, but the phones cannot detect each other. I have tried this with 3 different phones so I know it's not a hardware issue. In the image below, I should see the other phone pop up on the list but when I run "Scan" on both devices, each screen pops up with a long list of devices in the area that doesn't include the other device. I have also tried pressing "Scan" on just one of the phones at a time, and I have done all of the above both while the phones are already paired over Bluetooth and while they are not already paired.
I have not changed Google's code. Looking through the library, it seems that the DeviceScanActivity.java file is probably where the issue is occurring:
package com.example.android.bluetoothlegatt;
import android.app.Activity;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
/**
* Activity for scanning and displaying available Bluetooth LE devices.
*/
public class DeviceScanActivity extends ListActivity {
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle(R.string.title_devices);
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (!mScanning) {
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
} else {
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(
R.layout.actionbar_indeterminate_progress);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_scan:
mLeDeviceListAdapter.clear();
scanLeDevice(true);
break;
case R.id.menu_stop:
scanLeDevice(false);
break;
}
return true;
}
#Override
protected void onResume() {
super.onResume();
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
// fire an intent to display a dialog asking the user to grant permission to enable it.
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
if (device == null) return;
final Intent intent = new Intent(this, DeviceControlActivity.class);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
if (mScanning) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mScanning = false;
}
startActivity(intent);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
invalidateOptionsMenu();
}
// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflator = DeviceScanActivity.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if(!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflator.inflate(R.layout.listitem_device, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice device = mLeDevices.get(i);
final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 0)
viewHolder.deviceName.setText(deviceName);
else
viewHolder.deviceName.setText(R.string.unknown_device);
viewHolder.deviceAddress.setText(device.getAddress());
return view;
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
static class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
}
Be sure that your devices support Bluetooth LE multi broadcast.
Many devices support Bluetooth LE but not the multi broadcast feature.
You can install Beacon Simulator to be sure this feature is supported.
If yes, you should start the simulator to be discoverable.
See also this link
Android Beacon Library
Alright so currently my app turns on bluetooth on my device and then lists all paired devices in a List View. I am trying to make it so when the item in the list view is clicked it will connect to the device (primarily for bluetooth speakers). Below i have listed my main java file with all the code that runs my app. If anyone could get me going in the right direction id appreciate it. Also this is my first project working with bluetooth.
package com.applie.itchaboynathan.appv2;
import android.support.v7.app.AppCompatActivity;
import java.io.IOException;
import java.net.Socket;
import java.util.UUID;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.view.MenuItem;
import android.widget.Toast;
import android.bluetooth.BluetoothAdapter;
import android.widget.SeekBar;
import android.widget.TextView;
import android.content.Intent;
import android.widget.ListView;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import java.util.ArrayList;
import android.widget.ArrayAdapter;
import java.util.Set;
import android.os.Handler;
public class MainActivity extends AppCompatActivity {
private static SeekBar seek_bar;
private static TextView text_view;
private BluetoothAdapter BA;
private Set<BluetoothDevice>pairedDevices;
Handler handler = new Handler();
ListView lv;
ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
volumeBar();
BA = BluetoothAdapter.getDefaultAdapter();
lv = (ListView)findViewById(R.id.deviceList);
iv = (ImageView)findViewById(R.id.imgConnection);
//define menu button
ImageButton menubutton = (ImageButton)findViewById(R.id.ibtnMenu);
//enables the button to show a menu
menubutton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v){
final PopupMenu popupMenu = new PopupMenu(getApplicationContext(),v);
popupMenu.inflate(R.menu.main_menu);
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item){
switch (item.getItemId()) {
case R.id.connect:
//code for connect item
//Delay so the list creates
handler.postDelayed(new Runnable() {
#Override
public void run(){
list();
visible();
iv.setImageResource(R.mipmap.ic_checked);
}
}, 4200);
turnOn();
return true;
case R.id.disconnect:
//code for music item
turnOff();
iv.setImageResource(R.mipmap.ic_disconnected);
listClear();
return true;
case R.id.music:
//code for music item
return true;
case R.id.play:
//code for play item
return true;
case R.id.pause:
//code for pause item
return true;
}
return false;
}
});
}
});//end of button
}
//bluettoth enabler
public void turnOn(){
if (!BA.isEnabled()) {
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOn, 0);
Toast.makeText(getApplicationContext(), "Turned on",Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Already on", Toast.LENGTH_LONG).show();
}
}
//bluetooth disable
public void turnOff(){
BA.disable();
Toast.makeText(getApplicationContext(), "Turned off" ,Toast.LENGTH_LONG).show();
}
public void visible(){
Intent getVisible = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(getVisible, 0);
}
public void listClear(){
lv.setAdapter(null);
}
public void list(){
pairedDevices = BA.getBondedDevices();
ArrayList list = new ArrayList();
for(BluetoothDevice bt : pairedDevices) list.add(bt.getName());
Toast.makeText(getApplicationContext(), "Showing Paired Devices",Toast.LENGTH_SHORT).show();
final ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, list);
lv.setAdapter(adapter);
}
//volume bar code
public void volumeBar(){
seek_bar = (SeekBar)findViewById(R.id.seekBar);
text_view =(TextView)findViewById(R.id.txtVolumeLvl);
text_view.setText("Volume : " + seek_bar.getProgress() + " % ");
seek_bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
int progress_value;
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progress_value = progress;
text_view.setText("Volume : " + progress + " % ");
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
text_view.setText("Volume : " + progress_value + " % ");
}
}
);
}
//end volume bar
}
Try this:
ArrayList list = new ArrayList();
public void list(){
pairedDevices = BA.getBondedDevices();
for(BluetoothDevice bt : pairedDevices) list.add(bt.getName());
Toast.makeText(getApplicationContext(), "Showing Paired Devices",Toast.LENGTH_SHORT).show();
final ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener () {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
String selected = list.get(position);
for (Iterator<BluetoothDevice> it = pairedDevices.iterator(); it.hasNext(); ) {
BluetoothDevice bt = it.next();
if (bt.getName().equals(selected){
//connect to device
}
}
});
}
You have use BluetoothSocketfor connecting bluetooth.
use the below code to connect.
private BluetoothAdapter mBluetoothAdarpter;
private BluetoothSocket mBtSocket;
private BluetoothDevice mBTDevice;
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
..
..
private boolean connectToDevice(String iAdress) {
try {
if(mBluetoothAdarpter == null) mBluetoothAdarpter = BluetoothAdapter.getDefaultAdapter();
mBTDevice = mBluetoothAdarpter.getRemoteDevice(iAdress);
mBtSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID);
mBtSocket.connect();
return true;
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
I am writing one app to display user's current address based on latitude and longitude but i am getting one error in this code on line Toast.makeText(this, "No address found try again", Toast.LENGTH_SHORT).show(); It's saying makeText in the type toast is not applicable for arguments. I am unbable to resolve this error.
Any help??
I am trying to display user address in a TextView, but i am not sure whether i am doing good or some runtime error may occur in future.
Here is my Main activity java code:
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationServices;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnItemSelectedListener, ConnectionCallbacks, OnConnectionFailedListener{
private static final int REQUEST_RESOLVE_ERROR = 1001;
private static final String DIALOG_ERROR = "dialog_error";
private static final String STATE_RESOLVING_ERROR = "resolving_error";
GoogleApiClient mGoogleApiClient;
protected Location mLastLocation;
private boolean mResolvingError=false;
private AddressResultReceiver mResultReceiver;
// Request code to use when launching the resolution activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Spinner spinner = (Spinner) findViewById(R.id.shop_category);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.shop_category, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
mResolvingError = savedInstanceState != null
&& savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
TextView mytext = (TextView) view;
Toast.makeText(this,"You selected "+mytext.getText(),Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
protected void startIntentService() {
Intent intent = new Intent(this, FetchAddressIntentService.class);
intent.putExtra(Constants.RECEIVER, mResultReceiver);
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
startService(intent);
}
#Override
public void onConnected(Bundle arg0) {
boolean mAddressRequested=false;
// TODO Auto-generated method stub
TextView myLatitude = (TextView)findViewById(R.id.lat_value);
TextView myLongitude = (TextView)findViewById(R.id.lang_value);
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
myLatitude.setText(String.valueOf(mLastLocation.getLatitude()));
myLongitude.setText(String.valueOf(mLastLocation.getLongitude()));
if (!Geocoder.isPresent()) {
Toast.makeText(this, R.string.no_geocoder_available,
Toast.LENGTH_LONG).show();
return;
}
else{
mAddressRequested=true;
if (mAddressRequested) {
startIntentService();
}
}
}
}
#Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
if (mResolvingError) {
Toast.makeText(this, "Resolving errors", Toast.LENGTH_SHORT).show();
return;
} else if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
// Show dialog using GoogleApiAvailability.getErrorDialog()
showErrorDialog(result.getErrorCode());
mResolvingError = true;
}
}
private void showErrorDialog(int errorCode) {
// Create a fragment for the error dialog
ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
// Pass the error that should be displayed
Bundle args = new Bundle();
args.putInt(DIALOG_ERROR, errorCode);
dialogFragment.setArguments(args);
dialogFragment.show(getFragmentManager(), "errordialog");
}
public void onDialogDismissed() {
mResolvingError = false;
}
public static class ErrorDialogFragment extends DialogFragment {
public ErrorDialogFragment() { }
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get the error code and retrieve the appropriate dialog
int errorCode = this.getArguments().getInt(DIALOG_ERROR);
return GoogleApiAvailability.getInstance().getErrorDialog(
this.getActivity(), errorCode, REQUEST_RESOLVE_ERROR);
}
#Override
public void onDismiss(DialogInterface dialog) {
((MainActivity) getActivity()).onDialogDismissed();
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_RESOLVE_ERROR) {
mResolvingError = false;
if (resultCode == RESULT_OK) {
if (!mGoogleApiClient.isConnecting() &&
!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
}
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError);
}
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
class AddressResultReceiver extends ResultReceiver {
public AddressResultReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Display the address string
// or an error message sent from the intent service.
String mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
// Show a toast message if an address was found.
if (resultCode == Constants.SUCCESS_RESULT) {
TextView myaddress=(TextView) findViewById(R.id.myaddress);
myaddress.setText(mAddressOutput);
}
else{
Toast.makeText(this, "No address found try again", Toast.LENGTH_SHORT).show();
}
}
}
}
Thank you in advance.
Replace this with MainActivity.this as the first parameter to your makeText() call. this is an instance of your AddressResultReceiver inner class. It is not your activity, and makeText() needs a Context, like an Activity.
Use getApplicationContext() instead of this. Use:
Toast.makeText(getApplicationContext(), "message", Toast.LENGTH_SHORT).show();
this refers to AddressResultReceiver which is not subclass of Context.
Toast.makeText() needs Context.