Check Android device supports BLE.

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

		// Checks if Bluetooth is supported on the device.
		if (mBluetoothAdapter == null) {
			Toast.makeText(context, "Device does not supports BLE", Toast.LENGTH_SHORT).show();
			return;
		}
		else{
          Toast.makeText(context, "Device supports BLE", Toast.LENGTH_SHORT).show();
		}
	}

Leave a comment

UNEXPECTED TOP LEVEL EXCEPTION in android studio

Just add below code inside build.gradle

configurations {
    all*.exclude group: 'com.android.support', module: 'support-v4'
}

Leave a comment

Handle Failure [INSTALL_FAILED_OLDER_SDK] issue in Android Studio

I solved out it just now.
It seems that something wrong in SDK 20
I install SDK-19.0.1 and rewrite the file “build.gradle”

android {
    compileSdkVersion 19
    buildToolsVersion "19.1.0"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    // You must install or update the Google Repository through the SDK manager to use this dependency.
    compile 'com.android.support:appcompat-v7:19.+'
    compile 'com.android.support:support-v4:19.+'
}

success finally!

Leave a comment

How to implement UncaughtExceptionHandler in Android

If you do not handle a runtime exception in your program, the default behaviour will be to terminate the program and dump the call stacktrace on the console.

Java provides an elegant mechanism of handling Runtime Exceptions that you might have not handled in your program.
UncaughtExceptionHandler can be defined at three levels. From highest to lowest they are:

1.Thread.setDefaultUncaughtExceptionHandler
2.ThreadGroup.uncaughtException
3.Thread.setUncaughtExceptionHandler

package com.example.common;

import android.app.Activity;

public class TopExceptionHandler implements Thread.UncaughtExceptionHandler{
	
	private Activity objApp;

	public TopExceptionHandler(Activity app) {
		objApp = app;
		Thread.getDefaultUncaughtExceptionHandler();
	}

	@Override
	public void uncaughtException(Thread thread, Throwable ex) {
		// TODO Auto-generated method stub
		try{
			StackTraceElement[] arr = ex.getStackTrace();
			String report = ex.toString();
			
			String strStack = "";
			strStack += "Stack trace: ";
			for (int i=0; i<arr.length; i++){
				strStack += "    "+arr[i].toString()+"\t";
			}

			// If the exception was thrown in a background thread inside
			// AsyncTask, then the actual exception can be found with getCause
			String strCause = "";
			strCause += "Cause: ";
			Throwable cause = ex.getCause();
		}
		catch(Exception ex1){
			System.err.println(ex1);
		}
	}
}

Leave a comment

How to handle UncaughtException in Android

If you do not handle a runtime exception in your program, the default behaviour will be to terminate the program and dump the call stacktrace on the console.

Java provides an elegant mechanism of handling Runtime Exceptions that you might have not handled in your program.
UncaughtExceptionHandler can be defined at three levels. From highest to lowest they are:

1.Thread.setDefaultUncaughtExceptionHandler
2.ThreadGroup.uncaughtException
3.Thread.setUncaughtExceptionHandler

package com.example.common;

import android.app.Activity;

public class TopExceptionHandler implements Thread.UncaughtExceptionHandler{
	
	private Activity objApp;

	public TopExceptionHandler(Activity app) {
		objApp = app;
		Thread.getDefaultUncaughtExceptionHandler();
	}

	@Override
	public void uncaughtException(Thread thread, Throwable ex) {
		// TODO Auto-generated method stub
		try{
			StackTraceElement[] arr = ex.getStackTrace();
			String report = ex.toString();
			
			String strStack = "";
			strStack += "Stack trace: ";
			for (int i=0; i<arr.length; i++){
				strStack += "    "+arr[i].toString()+"\t";
			}

			// If the exception was thrown in a background thread inside
			// AsyncTask, then the actual exception can be found with getCause
			String strCause = "";
			strCause += "Cause: ";
			Throwable cause = ex.getCause();
		}
		catch(Exception ex1){
			System.err.println(ex1);
		}
	}
}

,

Leave a comment

Support BLE devices in android

For a given BLE device, this Activity provides the user interface to connect, display data,
and display GATT services and characteristics supported by the device. The Activity
communicates with {@code BluetoothLeService}, which in turn interacts with the Bluetooth LE API.

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ruiking.blesdk;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;

import com.ruiking.blelib.BluetoothLeService;
import com.ruiking.blelib.RKBluetoothManager;
import com.ruiking.blelib.Service;

/**
 * For a given BLE device, this Activity provides the user interface to connect, display data,
 * and display GATT services and characteristics supported by the device.  The Activity
 * communicates with {@code BluetoothLeService}, which in turn interacts with the
 * Bluetooth LE API.
 */
public class DeviceControlActivity extends Activity {
    private final static String TAG = DeviceControlActivity.class.getSimpleName();

    public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
    public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";

    private TextView mConnectionState;
    private TextView mDataField;
    private String mDeviceName;
    private String mDeviceAddress;
    private ExpandableListView mGattServicesList;
    private BluetoothLeService mBluetoothLeService;
    private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
            new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
    private boolean mConnected = false;
    private BluetoothGattCharacteristic mNotifyCharacteristic;

    private final String LIST_NAME = "NAME";
    private final String LIST_UUID = "UUID";
    private RKBluetoothManager mRKBluetoothManager;

    // Code to manage Service lifecycle.
    private final ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                finish();
            }
            // Automatically connects to the device upon successful start-up initialization.
            mBluetoothLeService.connect(mDeviceAddress);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBluetoothLeService = null;
        }
    };

    // Handles various events fired by the Service.
    // 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 a result of read
    //                        or notification operations.
    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
      		int status = intent.getIntExtra(BluetoothLeService.EXTRA_STATUS, BluetoothGatt.GATT_SUCCESS);
      		
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
                mConnected = true;
                updateConnectionState(R.string.connected);
                invalidateOptionsMenu();
                if(BluetoothLeService.getBtGatt() != null)
                {
                	BluetoothLeService.getBtGatt().discoverServices();
                }
            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
                mConnected = false;
                updateConnectionState(R.string.disconnected);
                invalidateOptionsMenu();
                clearUI();
            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                // Show all the supported services and characteristics on the user interface.
                displayGattServices(mBluetoothLeService.getSupportedGattServices());
            }
            else if (BluetoothLeService.ACTION_DATA_NOTIFY.equals(action)) {
      			// Notification
      			byte  [] value = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA);
      			String uuidStr = intent.getStringExtra(BluetoothLeService.EXTRA_UUID);
      			onCharacteristicChanged(uuidStr, value);
      		} else if (BluetoothLeService.ACTION_DATA_WRITE.equals(action)) {
      			// Data written
      			String uuidStr = intent.getStringExtra(BluetoothLeService.EXTRA_UUID);
      			onCharacteristicWrite(uuidStr,status);
      		} else if (BluetoothLeService.ACTION_DATA_READ.equals(action)) {
      			// Data read
      			String uuidStr = intent.getStringExtra(BluetoothLeService.EXTRA_UUID);
      			byte  [] value = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA);
      			onCharacteristicsRead(uuidStr,value,status);
      		}
        }
    };

    // If a given GATT characteristic is selected, check for supported features.  This sample
    // demonstrates 'Read' and 'Notify' features.  See
    // http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
    // list of supported characteristic features.
    private final ExpandableListView.OnChildClickListener servicesListClickListner =
            new ExpandableListView.OnChildClickListener() {
                @Override
                public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
                                            int childPosition, long id) {
                    if (mGattCharacteristics != null) {
                        final BluetoothGattCharacteristic characteristic =
                                mGattCharacteristics.get(groupPosition).get(childPosition);
                        final int charaProp = characteristic.getProperties();
                        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                            // If there is an active notification on a characteristic, clear
                            // it first so it doesn't update the data field on the user interface.
                            if (mNotifyCharacteristic != null) {
                                mBluetoothLeService.setCharacteristicNotification(
                                        mNotifyCharacteristic, false);
                                mNotifyCharacteristic = null;
                            }
                            mBluetoothLeService.readCharacteristic(characteristic);
                        }
                        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                            mNotifyCharacteristic = characteristic;
                            mBluetoothLeService.setCharacteristicNotification(
                                    characteristic, true);
                        }
                        return true;
                    }
                    return false;
                }
    };

    private void clearUI() {
        mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
        mDataField.setText(R.string.no_data);
    }

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

        final Intent intent = getIntent();
        mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
        mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);

        // Sets up UI references.
        ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
        mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);
        mGattServicesList.setOnChildClickListener(servicesListClickListner);
        mConnectionState = (TextView) findViewById(R.id.connection_state);
        mDataField = (TextView) findViewById(R.id.data_value);

//        getActionBar().setTitle(mDeviceName);
//        getActionBar().setDisplayHomeAsUpEnabled(true);
        mRKBluetoothManager = RKBluetoothManager.getInstance();
        mRKBluetoothManager.startBluetoothLeService(this, mServiceConnection);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
        if (mBluetoothLeService != null) {
            final boolean result = mBluetoothLeService.connect(mDeviceAddress);
            Log.d(TAG, "Connect request result=" + result);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mGattUpdateReceiver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
        mBluetoothLeService = null;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.gatt_services, menu);
        if (mConnected) {
            menu.findItem(R.id.menu_connect).setVisible(false);
            menu.findItem(R.id.menu_disconnect).setVisible(true);
        } else {
            menu.findItem(R.id.menu_connect).setVisible(true);
            menu.findItem(R.id.menu_disconnect).setVisible(false);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
            case R.id.menu_connect:
                mBluetoothLeService.connect(mDeviceAddress);
                return true;
            case R.id.menu_disconnect:
                mBluetoothLeService.disconnect(mDeviceAddress);
                return true;
            case android.R.id.home:
                onBackPressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void updateConnectionState(final int resourceId) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mConnectionState.setText(resourceId);
            }
        });
    }

    private void displayData(String data) {
        if (data != null) {
            mDataField.setText(data);
        }
    }

    // Demonstrates how to iterate through the supported GATT Services/Characteristics.
    // In this sample, we populate the data structure that is bound to the ExpandableListView
    // on the UI.
    private void displayGattServices(List<BluetoothGattService> gattServices) {
        if (gattServices == null) return;
        String uuid = null;
        String unknownServiceString = getResources().getString(R.string.unknown_service);
        String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
        ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
        ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
                = new ArrayList<ArrayList<HashMap<String, String>>>();
        mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

        // Loops through available GATT Services.
        for (BluetoothGattService gattService : gattServices) {
            HashMap<String, String> currentServiceData = new HashMap<String, String>();
            uuid = gattService.getUuid().toString();
            currentServiceData.put(
                    LIST_NAME, Service.lookup(uuid, unknownServiceString));
            currentServiceData.put(LIST_UUID, uuid);
            gattServiceData.add(currentServiceData);

            ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
                    new ArrayList<HashMap<String, String>>();
            List<BluetoothGattCharacteristic> gattCharacteristics =
                    gattService.getCharacteristics();
            ArrayList<BluetoothGattCharacteristic> charas =
                    new ArrayList<BluetoothGattCharacteristic>();

            // Loops through available Characteristics.
            for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                charas.add(gattCharacteristic);
                HashMap<String, String> currentCharaData = new HashMap<String, String>();
                uuid = gattCharacteristic.getUuid().toString();
                currentCharaData.put(
                        LIST_NAME, Service.lookup(uuid, unknownCharaString));
                currentCharaData.put(LIST_UUID, uuid);
                gattCharacteristicGroupData.add(currentCharaData);
            }
            mGattCharacteristics.add(charas);
            gattCharacteristicData.add(gattCharacteristicGroupData);
        }

        SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
                this,
                gattServiceData,
                R.layout.simple_expandable_list_item,
                new String[] {LIST_NAME, LIST_UUID},
                new int[] { android.R.id.text1, android.R.id.text2 },
                gattCharacteristicData,
                R.layout.simple_expandable_list_item,
                new String[] {LIST_NAME, LIST_UUID},
                new int[] { android.R.id.text1, android.R.id.text2 }
        );
        mGattServicesList.setAdapter(gattServiceAdapter);
    }

    private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_NOTIFY);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_WRITE);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_READ);
        return intentFilter;
    }

    private void onCharacteristicWrite(String uuidStr, int status) {
  	  Log.d(TAG,"onCharacteristicWrite: " + uuidStr);
    }

  	private void onCharacteristicChanged(String uuidStr, byte[] value) {
  		Log.d(TAG,"onCharacteristicChanged: " + uuidStr);
  	}

	private void onCharacteristicsRead(String uuidStr, byte[] value, int status) {
		Log.i(TAG, "onCharacteristicsRead: " + uuidStr);
		if (value != null && value.length > 0) {
			final StringBuilder stringBuilder = new StringBuilder(value.length);
			for (byte byteChar : value) {
				stringBuilder.append(String.format("%02X ", byteChar));
			}
			displayData(stringBuilder.toString());
		}
	}
}

Leave a comment

android.database.StaleDataException: Attempted to access a cursor after it has been closed.

During my android development, I came across this during run time:

android.database.StaleDataException: Attempted to access a cursor after it has been closed

I looked over the internet to look for solution on this issue. Many suggestions came out but only one suggestion solved “android.database.StaleDataException: Attempted to access a cursor after it has been closed” error.

It is by using startManagingCursor(cursor). The “cursor” is your result holder of your db query.

Recommend you that do not use startManagingCursor(cursor). Also it is deprecated.

Leave a comment

Follow

Get every new post delivered to your Inbox.