/*
* Copyright (C) 2015 Iasc CHEN
*
* 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 me.iasc.microduino.bluelight;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.*;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.*;
import android.widget.ImageView;
import android.widget.Toast;
import me.iasc.microduino.bluelight.ble.BluetoothLeService;
public abstract class AbstractBleControlActivity extends Activity {
private final static String TAG = AbstractBleControlActivity.class.getSimpleName();
public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
public static int BLE_MSG_SEND_INTERVAL = 60;
public static int BLE_MSG_BUFFER_LEN = 18;
protected String currDeviceName, currDeviceAddress;
protected Activity activity;
// protected TextView isSerial, mConnectionState;
protected ImageView infoButton;
protected BluetoothLeService mBluetoothLeService;
protected BluetoothGattCharacteristic characteristicTX, characteristicRX;
protected static boolean mConnected = false, characteristicReady = false;
protected StringBuilder msgBuffer;
// Code to manage Service lifecycle.
protected 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(currDeviceAddress);
}
@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.
protected final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
updateUnreadyState(R.string.unready);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
BluetoothGattService gattService = mBluetoothLeService.getSoftSerialService();
if (gattService == null) {
toastMessage(getString(R.string.without_service));
return;
}
if (currDeviceName.startsWith("Microduino")) {
characteristicTX = gattService.getCharacteristic(BluetoothLeService.UUID_MD_RX_TX);
} else if (currDeviceName.startsWith("EtOH")) {
characteristicTX = gattService.getCharacteristic(BluetoothLeService.UUID_ETOH_RX_TX);
}
characteristicRX = characteristicTX;
if (characteristicTX != null) {
mBluetoothLeService.setCharacteristicNotification(characteristicTX, true);
updateReadyState(R.string.ready);
} else {
// isSerial.setText("Serial can't be found");
updateUnreadyState(R.string.unready);
}
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(mBluetoothLeService.EXTRA_DATA));
}
}
};
protected 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_AVAILABLE);
return intentFilter;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this;
final Intent intent = getIntent();
currDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
currDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
// // Sets up UI references.
// mConnectionState = (TextView) findViewById(R.id.connection_state);
// // is serial present?
// isSerial = (TextView) findViewById(R.id.isSerial);
infoButton = (ImageView) findViewById(R.id.infoImage);
infoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
iascDialog();
}
});
getActionBar().setTitle(currDeviceName);
getActionBar().setDisplayHomeAsUpEnabled(true);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(currDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
@Override
protected void onResume() {
super.onResume();
// Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
// bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
//
// registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
// if (mBluetoothLeService != null) {
// final boolean result = mBluetoothLeService.connect(currDeviceAddress);
// Log.d(TAG, "Connect request result=" + result);
// }
}
@Override
protected void onPause() {
super.onPause();
// unregisterReceiver(mGattUpdateReceiver);
//
// unbindService(mServiceConnection);
// mBluetoothLeService = null;
}
@Override
protected void onDestroy() {
unregisterReceiver(mGattUpdateReceiver);
unbindService(mServiceConnection);
mBluetoothLeService = null;
super.onDestroy();
}
@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(false);
} 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(currDeviceAddress);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
protected void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// mConnectionState.setText(resourceId);
}
});
}
protected void updateUnreadyState(final int resourceId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
characteristicReady = false;
// isSerial.setText(getString(resourceId));
getActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.ble_unconnect)));
}
});
}
protected void updateReadyState(final int resourceId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
characteristicReady = true;
// isSerial.setText(getString(resourceId));
getActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.ble_connected)));
}
});
}
protected void displayData(String data) {
if (data != null) {
Log.v(TAG, "BLE Return Data : " + data);
}
}
public void wait_ble(int i) {
try {
Thread.sleep(i);
} catch (Exception e) {
// ignore
}
}
protected void sendMessage(String msg) {
Log.v(TAG, "sendMsg msg= " + msg);
if (characteristicReady && (mBluetoothLeService != null)
&& (characteristicTX != null) && (characteristicRX != null)) {
characteristicTX.setValue(msg);
mBluetoothLeService.writeCharacteristic(characteristicTX);
} else {
toastMessage(getString(R.string.disconnected));
}
}
protected void iascDialog() {
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.iasc_dialog,
(ViewGroup) findViewById(R.id.dialog));
new AlertDialog.Builder(this).setView(layout)
.setPositiveButton("OK", null).show();
}
public void toastMessage(String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
}