PART III - SETTING UP BLUETOOTH CONNECTION HANDLER
Skydiver's Blog
Coding for Beginners
Tutorial #1 Bluetooth Application for Android - Part II
PART II - SEARCHING & LISTING THE DEVICES
WORK IN PROGRESS
WORK IN PROGRESS
In this part of the tutorial, we are going to code the application so that it is able to turn on the Bluetooth on request and display the paired as well as the nearby devices in a list. We will make the User Interface through xml first and then add the required functionality in through the java code.
Open the file activity_main.xml in the editor from the layout folder.You can also open it by holding CTRL on windows and clicking the file name in setContentView(R.layout.activity_main) method of MainActivity.java. Once you have opened the file in the editor delete the default TextView block which shows Hello World. Also keep in mind that I am using the RelativeLayout in the root of my xml file. What a RelativeLayout means is that all the UI elements in the xml are placed relative to each other. There are two ways to make a UI in Android Studio
Open the file activity_main.xml in the editor from the layout folder.You can also open it by holding CTRL on windows and clicking the file name in setContentView(R.layout.activity_main) method of MainActivity.java. Once you have opened the file in the editor delete the default TextView block which shows Hello World. Also keep in mind that I am using the RelativeLayout in the root of my xml file. What a RelativeLayout means is that all the UI elements in the xml are placed relative to each other. There are two ways to make a UI in Android Studio
1. Using the design
2. Using the xml editor
The visual design supports drag and drop feature for the UI elements.You can just pick an element from the left pane and drag it on the screen. The screen size can be changed to view the response of UI elements on different screen size and density. This method is good for beginners who don't know a lot of programming. You can change the properties of a visual element by clicking it and editing values in the properties pane on the right side.
The other method is for programmers who like to have a clean and efficient code by using XML namespace and defining each property of the ui element in the XML file. I use a mix of both methods in my design. Firstly I place Ui elements on the screen using drag and drop and then I edit the code to my liking.
In this activity we are going to place a TextView, a ListView a Progress Bar and two buttons just drag these elements from the left palette and place them on the screen now open the file in editor. Now edit the file so as to make the design similar to the picture shown below. The XML code of the file is given below
Code: activity_main.xml
Code: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.skydiver.bluetoothtutorial.MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/progressBar"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignTop="@+id/progressBar"
android:layout_toLeftOf="@+id/progressBar"
android:gravity="center"
android:text="BLUETOOTH DEVICES"
android:textSize="20sp" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:visibility="visible" />
<ListView
android:id="@+id/device_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/buttons"
android:layout_below="@+id/textView" />
<LinearLayout
android:id="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/button_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Turn Bluetooth On"
android:layout_weight="0.6"/>
<Button
android:id="@+id/button_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scan Devices"
android:layout_weight="0.4"/>
</LinearLayout>
</RelativeLayout>
NOTE: If you are going to copy this code, please be sure to have the same app name as mine or errors will pop up
The design of the main activity is going to look like this image. The function of the textview here is to provide a heading for the Bluetooth devices. The progress bar shows the progress of scanning. By default the progress bar visibility is set to invisible and we will show it when scanning is done either the help of code. The listview holds all the Bluetooth devices that were either previously bonded or are in the vicinity. The toggle button turns the Bluetooth On and Off while the scan button starts the scanning of new devices in the vicinity.
Now we will start the java coding and add the behavior to these elements. Open the file MainActivity.java in the editor. Firstly I will show you all the code and then explain the working piece by piece. The code in the file MainActivity.java is given below
Code: MainActivity.java
Code: MainActivity.java
package com.skydiver.bluetoothtutorial; import android.Manifest; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.support.annotation.RequiresApi; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.Set; public class MainActivity extends AppCompatActivity { //Tag for debugging info in Logcat private static final String TAG = "Main Activity"; //Request codes for intents private final int REQUEST_ENABLE_BT = 1; private final int REQUEST_ENABLE_DISCOVERY = 2; private static final int REQUEST_COARSE_LOCATION = 5; //Local Bluetooth adapter private BluetoothAdapter mBluetoothAdapter = null; private Button toggleBTButton; private Button scanButton; private ListView devicesList; private ProgressBar progressBar; ArrayList<String> arrayList = new ArrayList<>(); ArrayAdapter<String> devicesArrayAdapter; Set<BluetoothDevice> pairedDevices; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get reference to local Bluetooth adapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // Giving references to views devicesList = (ListView) findViewById(R.id.device_list); scanButton = (Button) findViewById(R.id.button_scan); toggleBTButton = (Button) findViewById(R.id.button_toggle); progressBar = (ProgressBar) findViewById(R.id.progressBar); //Assigning listeners to buttons and list scanButton.setOnClickListener(mScanClickListener); toggleBTButton.setOnClickListener(mToggleClickListener); devicesList.setOnItemClickListener(mDeviceClickListener); devicesArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,arrayList); devicesList.setAdapter(devicesArrayAdapter); // Register for broadcasts when a device is discovered IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter); // Register for broadcasts when discovery has finished filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); } /** * Makes this device discoverable. */ private void ensureDiscoverable() { if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120); startActivity(discoverableIntent); } } /** * Start device discovery with the BluetoothAdapter */ private void doDiscovery() { Log.e(TAG, "doDiscovery()"); // If we're already discovering, stop it if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } // Request discover from BluetoothAdapter mBluetoothAdapter.startDiscovery(); // Indicate scanning through a ProgressBar progressBar.setVisibility(View.VISIBLE); } View.OnClickListener mScanClickListener = new View.OnClickListener() { @Override public void onClick(View view) { if (mBluetoothAdapter == null) { refreshButtonState(); Toast.makeText(getApplicationContext(), "Bluetooth Device not available!", Toast.LENGTH_SHORT).show(); } else if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } loadPairedDevices(); ensureDiscoverable(); checkLocationPermissions(); } }; View.OnClickListener mToggleClickListener = new View.OnClickListener() { @Override public void onClick(View view) { toggleBluetooth(); } }; /** * The on-item-click listener for all devices in the ListViews */ private AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() { @RequiresApi(api = Build.VERSION_CODES.KITKAT) public void onItemClick(AdapterView<?> av, View v, int position, long id) { // Cancel discovery because it's costly and we're about to connect mBluetoothAdapter.cancelDiscovery(); // Get the device MAC address, which is the last 17 chars in the View String info = ((TextView) v).getText().toString(); String address = info.substring(info.length() - 17); BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); if(device.getBondState()==BluetoothDevice.BOND_NONE){ try { device.createBond(); Log.e(TAG , "Bond created"); } catch (Exception e) { e.printStackTrace(); Log.e(TAG , "Bond creation failed"); } } } }; @Override protected void onDestroy() { super.onDestroy(); // Make sure we're not doing discovery anymore if (mBluetoothAdapter != null) { mBluetoothAdapter.cancelDiscovery(); } // Unregister broadcast listeners this.unregisterReceiver(mReceiver); } /** * The BroadcastReceiver that listens for discovered devices and changes the title when * discovery is finished */ private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device if (action.equals(BluetoothDevice.ACTION_FOUND)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.e(TAG, "Device Found : " + device.getName() + " Address : " + device.getAddress()); // If it's already paired, skip it, because it's been listed already if (device.getBondState() != BluetoothDevice.BOND_BONDED) { devicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); devicesArrayAdapter.notifyDataSetChanged(); } // When discovery is finished, change the Activity title } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { progressBar.setVisibility(View.INVISIBLE); Log.e(TAG, "Discovery Finished"); if (devicesArrayAdapter.getCount() == 0) { Toast.makeText(getApplicationContext(), "No Devices Discovered", Toast.LENGTH_SHORT).show(); } } } }; /** * Load the list of already paired devices */ public void loadPairedDevices() { devicesArrayAdapter.clear(); pairedDevices = mBluetoothAdapter.getBondedDevices(); if (mBluetoothAdapter.getBondedDevices().size() > 0) { for (BluetoothDevice device : pairedDevices) { Log.e(TAG, "Paired Device : " + device.getName() + " Address : " + device.getAddress()); arrayList.add(device.getName() + "\n" + device.getAddress()); } } else { devicesArrayAdapter.add("No Paired Devices"); devicesArrayAdapter.notifyDataSetChanged(); } } /** * Toggle the state of bluetooth adapter on button click */ private void toggleBluetooth() { if (mBluetoothAdapter == null) { refreshButtonState(); Toast.makeText(getApplicationContext(), "Bluetooth Device not available!", Toast.LENGTH_SHORT).show(); } else if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } else if (mBluetoothAdapter.isEnabled()) { mBluetoothAdapter.disable(); Toast.makeText(getApplicationContext(), "Bluetooth turned off", Toast.LENGTH_SHORT).show(); } refreshButtonState(); } /** * Refresh the button state if bluetooth state is changed */ private void refreshButtonState() { Log.e(TAG, "Button State Refreshed"); if (mBluetoothAdapter != null) { if (mBluetoothAdapter.isEnabled()) { toggleBTButton.setText("Turn Bluetooth Off"); } else if (!mBluetoothAdapter.isEnabled()) { toggleBTButton.setText("Turn Bluetooth On"); } } else { toggleBTButton.setText("Bluetooth adapter unavailable"); toggleBTButton.setEnabled(false); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_ENABLE_BT: if (resultCode == RESULT_OK) { refreshButtonState(); Toast.makeText(getApplicationContext(), "Bluetooth enabled Successfully", Toast.LENGTH_SHORT).show(); loadPairedDevices(); } else if (resultCode == RESULT_CANCELED) { Toast.makeText(getApplicationContext(), "Action cancelled by User!", Toast.LENGTH_SHORT).show(); refreshButtonState(); } else { refreshButtonState(); Toast.makeText(getApplicationContext(), "Bluetooth couldn't be enabled!", Toast.LENGTH_SHORT).show(); } case REQUEST_ENABLE_DISCOVERY: if (resultCode == RESULT_CANCELED) Toast.makeText(getApplicationContext(), "Discovery Started", Toast.LENGTH_SHORT).show(); } super.onActivityResult(requestCode, resultCode, data); } @Override protected void onResume() { super.onResume(); refreshButtonState(); } /** * Location Permission required for scanning devices starting from Android 6.0 Marshmallow */ protected void checkLocationPermissions() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_COARSE_LOCATION); } } else doDiscovery(); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case REQUEST_COARSE_LOCATION: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { doDiscovery(); } else { //Toast.makeText(this, "Permission required for \n discovering devices",Toast.LENGTH_LONG).show(); checkLocationPermissions(); } break; } } } }
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.skydiver.bluetoothtutorial" >
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Tutorial #1 Bluetooth Application for Android - Part I
PART I - SETTING UP THE PROJECT
Hello friends , this is going to be the first tutorial on my blog. I am going to start a tutorial on making a fully functional Bluetooth application for Android. When I was making a project on Arduino platform I wanted to make the Bluetooth functionality through android app myself rather than downloading and installing an application from the Play Store. I looked for tutorials related to that. I found many tutorials but most of them were limited to searching Bluetooth devices and listing them(not to mention only the paired one). Even If I found some full tutorial, it was very difficult to understand for a beginner. So I have decided to write this post and make it as simple as possible for the beginners and noobs.
Requirements for learning this tutorial :
1. Android Studio installed on your system be it Mac, Windows of Linux
1. Android Studio installed on your system be it Mac, Windows of Linux
2. Basic programming skills
3. Little knowledge of core java won't hurt
So let's start by opening the Android Studio
So let's start by opening the Android Studio
Start a new project in the Android Studio. Give it a name you want and click next button.
Select the minimum Android version that can run the application. I am choosing Android 4.0 as devices with lower API are almost none. Now click next to continue.
In the next window create an empty activity and give it a suitable name. I am using the default name so to follow this tutorial choose the same name. Click finish to move to the code editor.
Now let the gradle sync and build the index. If the gradle sync fails due to an error refer google for troubleshooting.This is the end of part I of this tutorial. Click here to part II of this tutorial.
Subscribe to:
Posts (Atom)
Featured Post
Tutorial #1 Bluetooth Application for Android - Part I
PART I - SETTING UP THE PROJECT Hello friends , this is going to be the first tutorial on my blog. I am going to start a tutorial on ...
-
PART II - SEARCHING & LISTING THE DEVICES WORK IN PROGRESS In this part of the tutorial, we are going to code the application so t...
-
PART I - SETTING UP THE PROJECT Hello friends , this is going to be the first tutorial on my blog. I am going to start a tutorial on ...
-
PART IV TRANSFERRING DATA BETWEEN DEVICES