package com.shiitakeo.android_wear_for_ios; import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.app.Notification; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSocket; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Build; import android.os.IBinder; import android.os.ParcelUuid; import android.os.PowerManager; import android.os.Vibrator; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationManagerCompat; import android.support.v4.content.LocalBroadcastManager; import android.support.wearable.activity.ConfirmationActivity; import android.util.Log; import java.io.DataOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; /** * Created by shiitakeo on 15/03/15. */ public class BLEService extends Service{ // BluetoothLeScanner does not work properly in my environment... // private int api_level = Build.VERSION.SDK_INT; private int api_level = 20; private BluetoothAdapter bluetooth_adapter; private BluetoothGatt bluetooth_gatt; private static Boolean is_connect = false; private static final String TAG_LOG = "BLE_wear"; //ANCS Profile private static final String service_ancs = "7905f431-b5ce-4e99-a40f-4b1e122d00d0"; private static final String characteristics_notification_source = "9fbf120d-6301-42d9-8c58-25e699a21dbd"; private static final String characteristics_data_source = "22eac6e9-24d6-4bb5-be44-b36ace7c7bfb"; private static final String characteristics_control_point = "69d1d8f3-45e1-49a8-9821-9bbdfdaad9d9"; private static final String descriptor_config = "00002902-0000-1000-8000-00805f9b34fb"; private static final String service_blank = "00001111-0000-1000-8000-00805f9b34fb"; //CTS Profile private static final String service_cts = "00001805-0000-1000-8000-00805f9b34fb"; private static final String characteristics_current_time = "00002a2b-0000-1000-8000-00805f9b34fb"; private Boolean is_subscribed_characteristics = false; private Vibrator vib; private long pattern[] = {200, 100, 200, 100}; private BluetoothLeScanner le_scanner; private NotificationManagerCompat notificationManager; private int notification_id = 0; private PowerManager.WakeLock wake_lock; private PacketProcessor packet_processor; private IconImageManager icon_image_manager; private BroadcastReceiver message_receiver = new MessageReceiver(); private byte[] uid = new byte[4]; // intent action String action_positive = "com.shiitakeo.perform_notification_action_positive"; String action_negative = "com.shiitakeo.perform_notification_action_negative"; String action_delete = "com.shiitakeo.delete"; String action_renotify = "com.shiitakeo.renotify"; String action_set_clock = "com.shiitakeo.set_clock"; String extra_uid = "com.shiitakeo.extra_uid"; private static final long screen_time_out = 1000; private Boolean is_reconnect = false; BLEScanCallback scan_callback = new BLEScanCallback(); String iphone_uuid; private int skip_count = 0; long start_time; Boolean is_time = false; //notification id int id_music_control = 99; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.d(TAG_LOG, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } @TargetApi(20) @Override public void onStart(Intent intent, int startID) { Log.d(TAG_LOG, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); IntentFilter intent_filter = new IntentFilter(); intent_filter.addAction(action_positive); intent_filter.addAction(action_negative); intent_filter.addAction(action_delete); intent_filter.addAction(action_renotify); registerReceiver(message_receiver, intent_filter); vib = (Vibrator)getSystemService(VIBRATOR_SERVICE); notificationManager = NotificationManagerCompat.from(getApplicationContext()); packet_processor = new PacketProcessor(); icon_image_manager = new IconImageManager(); if(bluetooth_gatt != null) { bluetooth_gatt.disconnect(); bluetooth_gatt.close(); bluetooth_gatt = null; } if(bluetooth_adapter != null) { bluetooth_adapter = null; } if(api_level >= 21) { if (le_scanner != null) { Log.d(TAG_LOG, "status: ble reset"); stop_le_scanner(); } } is_connect = false; is_subscribed_characteristics = false; iphone_uuid = ""; start_time = 0; is_time = false; // 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); bluetooth_adapter = bluetoothManager.getAdapter(); // Checks if Bluetooth is supported on the device. if (bluetooth_adapter == null) { Log.d(TAG_LOG, "ble adapter is null"); return; } if(api_level >= 21) { Log.d(TAG_LOG, "start BLE scan @ lescan"); start_le_scanner(); }else { Log.d(TAG_LOG, "start BLE scan @ BluetoothAdapter"); bluetooth_adapter.startLeScan(le_scan_callback); } //music control notification Intent __intent = new Intent(this, MusicControlActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, __intent, 0); Intent _intent_delete = new Intent(); _intent_delete.setAction(action_renotify); PendingIntent _delete_action = PendingIntent.getBroadcast(getApplicationContext(), notification_id, _intent_delete, PendingIntent.FLAG_ONE_SHOT); Notification.Builder notificationBuilder = new Notification.Builder(this) .setSmallIcon(R.drawable.whatsapp) .setContentTitle("music💿") .setContentIntent(pendingIntent) .addAction(R.drawable.resume, "Controller Open", pendingIntent) .setLocalOnly(true) // .setPriority(Notification.PRIORITY_MIN) // .setPriority(-100) .setDeleteIntent(_delete_action) .extend(new Notification.WearableExtender().setContentAction(0).setHintHideIcon(true)) ; Notification _notification = notificationBuilder.build(); // _notification.flags = _notification.flags | Notification.FLAG_ONGOING_EVENT; NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notificationManager.notify(id_music_control, _notification); notification_id++; } @TargetApi(21) private void start_le_scanner(){ le_scanner = bluetooth_adapter.getBluetoothLeScanner(); // ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).build(); // le_scanner.startScan(scan_fillters(), settings, scan_callback); le_scanner.startScan(scan_callback); } @TargetApi(21) private void stop_le_scanner(){ le_scanner.stopScan(scan_callback); } @Override public void onDestroy() { Log.d(TAG_LOG, "~~~~~~~~ service onDestroy"); if(api_level >= 21) { stop_le_scanner(); }else { bluetooth_adapter.stopLeScan(le_scan_callback); } is_connect =false; is_subscribed_characteristics = false; iphone_uuid = ""; is_time = false; if(null != bluetooth_gatt){ bluetooth_gatt.disconnect(); bluetooth_gatt.close(); bluetooth_gatt = null; } bluetooth_adapter = null; if(notificationManager != null) { notificationManager.cancel(id_music_control); notificationManager.cancelAll(); notificationManager = null; } super.onDestroy(); } private List<ScanFilter> scan_fillters() { // can't find ancs service return create_scan_filter(); } @TargetApi(21) private List<ScanFilter> create_scan_filter(){ // ScanFilter filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(service_ancs)).build(); ScanFilter filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(service_blank)).build(); List<ScanFilter> list = new ArrayList<ScanFilter>(1); list.add(filter); return list; } @TargetApi(21) private class BLEScanCallback extends ScanCallback { @Override public void onScanResult(int callbackType, android.bluetooth.le.ScanResult result) { Log.d(TAG_LOG, "scan result" + result.toString()); BluetoothDevice device = result.getDevice(); if (!is_connect) { Log.d(TAG_LOG, "is connect"); if (device != null) { Log.d(TAG_LOG, "device "); if (!is_reconnect && device.getName() != null) { if(device.getName().equals("Blank")) { // if(device.getName().equals("BLE Utility")) { Log.d(TAG_LOG, "getname "); iphone_uuid = device.getAddress().toString(); is_connect = true; bluetooth_gatt = result.getDevice().connectGatt(getApplicationContext(), false, bluetooth_gattCallback); } } else if (is_reconnect && device.getAddress().toString().equals(iphone_uuid)) { if(!is_time) { Log.d(TAG_LOG, "-=-=-=-=-=-=-=-=-=- timer start:: -=-==-=-=-=-=-=-==--=-=-=-==-=-=-=-=-=-=-=-"); start_time = System.currentTimeMillis(); is_time = true; }else if(System.currentTimeMillis() - start_time > 5000){ Log.d(TAG_LOG, "-=-=-=-=-=-=-=-=-=- reconnect:: -=-==-=-=-=-=-=-==--=-=-=-==-=-=-=-=-=-=-=-"); is_connect = true; is_reconnect = false; bluetooth_gatt = device.connectGatt(getApplicationContext(), true, bluetooth_gattCallback); } } else { Log.d(TAG_LOG, "skip:: "); skip_count++; } } } }; @Override public void onBatchScanResults(List<ScanResult> results) { Log.i(TAG_LOG, "batchscan result" + results.toString()); } @Override public void onScanFailed(int errorCode) { super.onScanFailed(errorCode); Log.d(TAG_LOG, "onScanFailed" + errorCode); } } // }; private BluetoothAdapter.LeScanCallback le_scan_callback = new BluetoothAdapter.LeScanCallback(){ @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { Log.i(TAG_LOG, "onLeScan"); if (!is_connect) { Log.d(TAG_LOG, "is connect"); if (device != null) { Log.d(TAG_LOG, "device "); if (!is_reconnect && device.getName() != null) { // if(device.getName().equals("Blank")) { if(device.getName().equals("BLE Utility")) { Log.d(TAG_LOG, "getname "); iphone_uuid = device.getAddress().toString(); Log.d(TAG_LOG, "iphone_uuid: " + iphone_uuid); is_connect = true; bluetooth_gatt = device.connectGatt(getApplicationContext(), false, bluetooth_gattCallback); } } else if (is_reconnect && device.getAddress().toString().equals(iphone_uuid)) { if(!is_time) { Log.d(TAG_LOG, "-=-=-=-=-=-=-=-=-=- timer start:: -=-==-=-=-=-=-=-==--=-=-=-==-=-=-=-=-=-=-=-"); start_time = System.currentTimeMillis(); is_time = true; }else if(System.currentTimeMillis() - start_time > 5000){ Log.d(TAG_LOG, "-=-=-=-=-=-=-=-=-=- reconnect:: -=-==-=-=-=-=-=-==--=-=-=-==-=-=-=-=-=-=-=-"); is_connect = true; is_reconnect = false; // get paired devices Set<BluetoothDevice> _paired_devices = bluetooth_adapter.getBondedDevices(); for(BluetoothDevice _paired_device: _paired_devices) { Log.d(TAG_LOG, "paired device: " + _paired_device + " :: " + _paired_device.getName()); Log.d(TAG_LOG, "++ " + _paired_device.getAddress() + " :: " + _paired_device.getUuids()); if(_paired_device.getAddress().toString().equals(iphone_uuid)) { Log.d(TAG_LOG, "*=*=8=*+*+8=8+*+8=*+*+*=8+*+*8+*+*=*+*+*=8+*+*+8+*+*+*=*+8=*+8+*+8=8+*="); try { BluetoothSocket bluetooth_socket = _paired_device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); bluetooth_socket.connect(); } catch (IOException e) { e.printStackTrace(); } } } Log.d(TAG_LOG, "connect gatt"); bluetooth_gatt = device.connectGatt(getApplicationContext(), false, bluetooth_gattCallback); } } else { Log.d(TAG_LOG, "skip:: "); skip_count++; } } } } }; private final BluetoothGattCallback bluetooth_gattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { Log.d(TAG_LOG, "onConnectionStateChange: " + status + " -> " + newState); if (newState == BluetoothProfile.STATE_CONNECTED) { // success, connect to gatt. // find service gatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.d(TAG_LOG, "onDisconnect: "); if(api_level >= 21) { if (le_scanner != null) { Log.d(TAG_LOG, "status: ble reset"); stop_le_scanner(); } } if(bluetooth_gatt != null) { bluetooth_gatt.disconnect(); bluetooth_gatt.close(); bluetooth_gatt = null; } if(bluetooth_adapter != null) { bluetooth_adapter = null; } is_connect = false; is_subscribed_characteristics = false; skip_count = 0; is_time = false; // 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); bluetooth_adapter = bluetoothManager.getAdapter(); // Checks if Bluetooth is supported on the device. if (bluetooth_adapter == null) { Log.d(TAG_LOG, "ble adapter is null"); return; } is_reconnect = true; Log.d(TAG_LOG, "start BLE scan"); if(api_level >= 21) { start_le_scanner(); }else { bluetooth_adapter.startLeScan(le_scan_callback); } } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { Log.d(TAG_LOG, "onServicesDiscovered received: " + status); if (status == BluetoothGatt.GATT_SUCCESS) { BluetoothGattService service = gatt.getService(UUID.fromString(service_ancs)); if (service == null) { Log.d(TAG_LOG, "cant find service"); } else { Log.d(TAG_LOG, "find service"); Log.d(TAG_LOG, String.valueOf(bluetooth_gatt.getServices())); // subscribe data source characteristic BluetoothGattCharacteristic data_characteristic = service.getCharacteristic(UUID.fromString(characteristics_data_source)); if (data_characteristic == null) { Log.d(TAG_LOG, "cant find data source chara"); } else { Log.d(TAG_LOG, "find data source chara :: " + data_characteristic.getUuid()); Log.d(TAG_LOG, "set notify:: " + data_characteristic.getUuid()); bluetooth_gatt.setCharacteristicNotification(data_characteristic, true); BluetoothGattDescriptor descriptor = data_characteristic.getDescriptor( UUID.fromString(descriptor_config)); if(descriptor == null){ Log.d(TAG_LOG, " ** cant find desc :: " + descriptor.getUuid()); }else{ Log.d(TAG_LOG, " ** find desc :: " + descriptor.getUuid()); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); bluetooth_gatt.writeDescriptor(descriptor); if(api_level >= 21) { stop_le_scanner(); }else { bluetooth_adapter.stopLeScan(le_scan_callback); } } } } } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.d(TAG_LOG, "onCharacteristicRead:: " + status); if (status == BluetoothGatt.GATT_SUCCESS) { //set current time //need rooted wear device Log.d(TAG_LOG, "8=8==8=8=8=8===8=8=8=8=8=8==8=8=8=8=8==88=8=8=8="); String month_prefix = ""; String day_prefix = ""; String hour_prefix = ""; String min_prefix = ""; String sec_prefix = ""; int year = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT16, 0); Log.d(TAG_LOG, "year:: " + year); int month = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 2); if (month < 10) { month_prefix = new String("0" + month); Log.d(TAG_LOG, "month_pre:: " + month_prefix); } else { month_prefix = String.valueOf(month); Log.d(TAG_LOG, "month_pre:: " + month_prefix); } int day = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 3); if (day < 10) { day_prefix = new String("0" + day); Log.d(TAG_LOG, "day_pre:: " + day_prefix); } else { day_prefix = String.valueOf(day); Log.d(TAG_LOG, "day_pre:: " + day_prefix); } int hour = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 4); if (hour < 10) { hour_prefix = new String("0" + hour); Log.d(TAG_LOG, "hour_pre:: " + hour_prefix); } else { hour_prefix = String.valueOf(hour); Log.d(TAG_LOG, "hour_pre:: " + hour_prefix); } int min = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 5); if (min < 10) { min_prefix = new String("0" + min); Log.d(TAG_LOG, "min_pre:: " + min_prefix); } else { min_prefix = String.valueOf(min); Log.d(TAG_LOG, "min_pre:: " + min_prefix); } int sec = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 6); if (sec < 10) { sec_prefix = new String("0" + sec); Log.d(TAG_LOG, "sec_pre:: " + sec_prefix); } else { sec_prefix = String.valueOf(sec); Log.d(TAG_LOG, "sec_pre:: " + sec_prefix); } int date = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 7); Log.d(TAG_LOG, "date:: " + date); try { Process process = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(process.getOutputStream()); String set_time = new String("date -s " + year + month_prefix + day_prefix + "." + hour_prefix + min_prefix + sec_prefix); Log.d(TAG_LOG, "set_time: " + set_time); os.writeBytes(set_time); } catch (IOException e) { e.printStackTrace(); } } } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { Log.d(TAG_LOG, " onDescriptorWrite:: " + status); // Notification source if (status == BluetoothGatt.GATT_SUCCESS){ Log.d(TAG_LOG, "status: write success "); if (!is_subscribed_characteristics) { //subscribe characteristic notification characteristic BluetoothGattService service = gatt.getService(UUID.fromString(service_ancs)); BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(characteristics_notification_source)); // if (characteristic == null) { Log.d(TAG_LOG, " cant find chara"); } else { Log.d(TAG_LOG, " ** find chara :: " + characteristic.getUuid()); if (characteristics_notification_source.equals(characteristic.getUuid().toString())) { Log.d(TAG_LOG, " set notify:: " + characteristic.getUuid()); bluetooth_gatt.setCharacteristicNotification(characteristic, true); BluetoothGattDescriptor notify_descriptor = characteristic.getDescriptor( UUID.fromString(descriptor_config)); if (descriptor == null) { Log.d(TAG_LOG, " ** not find desc :: " + notify_descriptor.getUuid()); } else { Log.d(TAG_LOG, " ** find desc :: " + notify_descriptor.getUuid()); notify_descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); bluetooth_gatt.writeDescriptor(notify_descriptor); is_subscribed_characteristics = true; } } } }else { //execute success animation Intent intent = new Intent(getApplicationContext(), ConfirmationActivity.class); intent.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE, ConfirmationActivity.SUCCESS_ANIMATION); intent.putExtra(ConfirmationActivity.EXTRA_MESSAGE, "success"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); // get current time Log.d(TAG_LOG, ":get time+_=-=_=-+-+-+-=_=_=_+-=-=-=-="); BluetoothGattService _service = gatt.getService(UUID.fromString(service_cts)); if (_service == null) { Log.d(TAG_LOG, "cant find service"); } else { Log.d(TAG_LOG, "find service"); Log.d(TAG_LOG, String.valueOf(bluetooth_gatt.getServices())); // subscribe data source characteristic BluetoothGattCharacteristic data_characteristic = _service.getCharacteristic(UUID.fromString(characteristics_current_time)); if (data_characteristic == null) { Log.d(TAG_LOG, "cant find data source chara"); } else { Log.d(TAG_LOG, "find data source chara :: " + data_characteristic.getUuid()); gatt.readCharacteristic(data_characteristic); } } } }else if(status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { Log.d(TAG_LOG, "status: write not permitted"); //remove authrization Method method = null; try { method = gatt.getDevice().getClass().getMethod("removeBond", (Class[]) null); method.invoke(gatt.getDevice(), (Object[]) null); } catch (Exception e) { e.printStackTrace(); } gatt.disconnect(); Log.d(TAG_LOG, "onDisconnect: "); if(api_level >= 21) { if (le_scanner != null) { Log.d(TAG_LOG, "status: ble reset"); stop_le_scanner(); } } if(bluetooth_gatt != null) { bluetooth_gatt.disconnect(); bluetooth_gatt.close(); bluetooth_gatt = null; } if(bluetooth_adapter != null) { bluetooth_adapter = null; } is_connect = false; is_subscribed_characteristics = false; skip_count = 0; is_time = false; // 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); bluetooth_adapter = bluetoothManager.getAdapter(); // Checks if Bluetooth is supported on the device. if (bluetooth_adapter == null) { Log.d(TAG_LOG, "ble adapter is null"); return; } is_reconnect = true; Log.d(TAG_LOG, "start BLE scan"); if(api_level >= 21) { start_le_scanner(); }else { bluetooth_adapter.startLeScan(le_scan_callback); } } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { Log.d(TAG_LOG, "onCharacteristicChanged:: " + characteristic.getUuid().toString()); //notify from data source characteristic //process get notitification packet from iphone. if (characteristics_data_source.toString().equals(characteristic.getUuid().toString())) { byte[] get_data = characteristic.getValue(); // if(DEBUG){ // StringBuilder stringBuilder = new StringBuilder(); // for (byte byteChar : get_data) { // stringBuilder.append(String.format("%02X", byteChar)); // } // // Log.d(TAG_LOG, "notify value:: " + stringBuilder.toString()); // } packet_processor.processing(get_data); if(packet_processor.is_finish_processing()){ int app_logo = icon_image_manager.get_image_index(packet_processor.get_ds_app_id()); Bitmap large_icon = BitmapFactory.decodeResource(getResources(), app_logo); Log.d(TAG_LOG, "in title: notification"); byte[] _uid = packet_processor.get_uid(); //create perform notification action pending_intent Intent _intent_positive = new Intent(); _intent_positive.setAction(action_positive); _intent_positive.putExtra(extra_uid, _uid); PendingIntent _positive_action = PendingIntent.getBroadcast(getApplicationContext(), notification_id, _intent_positive, PendingIntent.FLAG_ONE_SHOT); Intent _intent_negative = new Intent(); _intent_negative.setAction(action_negative); _intent_negative.putExtra(extra_uid, _uid); //0 => notification_idでインクリメントしてる PendingIntent _negative_action = PendingIntent.getBroadcast(getApplicationContext(), notification_id, _intent_negative, PendingIntent.FLAG_ONE_SHOT); Intent _intent_delete = new Intent(); _intent_delete.setAction(action_delete); _intent_delete.putExtra(extra_uid, _uid); PendingIntent _delete_action = PendingIntent.getBroadcast(getApplicationContext(), notification_id, _intent_delete, PendingIntent.FLAG_ONE_SHOT); Notification notification = new NotificationCompat.Builder(getApplicationContext()) .setContentTitle(packet_processor.get_ds_title()) .setContentText(packet_processor.get_ds_message()) .setSmallIcon(app_logo) .setLargeIcon(large_icon) .setGroup(packet_processor.get_ds_app_id()) .addAction(R.drawable.ic_accept, "Accept", _positive_action) .addAction(R.drawable.ic_decline, "Decline", _negative_action) .setDeleteIntent(_delete_action) .setPriority(Notification.PRIORITY_HIGH) .build(); // //notification_id => mediaとかREGULARで固定してる //UIDから生成するユニークなtagをつかっている.タグを使う場合,タグとIDのペアがユニークであればよい. notificationManager.notify(notification_id, notification); notification_id++; vib.vibrate(pattern, -1); // awake screen. PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); wake_lock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "MyWakelockTag"); if (!wake_lock.isHeld()) { Log.d(TAG_LOG, "acquire()"); wake_lock.acquire(screen_time_out); } } } //notify from characteristic notification characteristic if (characteristics_notification_source.toString().equals(characteristic.getUuid().toString())) { Log.d(TAG_LOG, "get notify from notification source chara"); //init packet processing flag; packet_processor.init(); byte[] data = characteristic.getValue(); if(data != null && data.length > 0) { try { if (String.format("%02X", data[0]).equals("00")) { Log.d(TAG_LOG, "get notify"); // notification value setting. //current, hard coding uid[0] = data[4]; uid[1] = data[5]; uid[2] = data[6]; uid[3] = data[7]; byte[] get_notification_attribute = { (byte)0x00, //UID data[4], data[5], data[6], data[7], //app id (byte)0x00, //title (byte)0x01, (byte)0xff, (byte)0xff, //message (byte)0x03, (byte)0xff, (byte)0xff }; BluetoothGattService service = gatt.getService(UUID.fromString(service_ancs)); if (service == null) { Log.d(TAG_LOG, "cant find service"); } else { Log.d(TAG_LOG, "find service"); characteristic = service.getCharacteristic(UUID.fromString(characteristics_control_point)); if (characteristic == null) { Log.d(TAG_LOG, "cant find chara"); } else { Log.d(TAG_LOG, "find chara"); characteristic.setValue(get_notification_attribute); gatt.writeCharacteristic(characteristic); } } } }catch(ArrayIndexOutOfBoundsException e){ Log.d(TAG_LOG, "error"); e.printStackTrace(); } } } } }; @TargetApi(20) public class MessageReceiver extends BroadcastReceiver{ private static final String TAG_LOG = "BLE_wear"; @Override public void onReceive(Context context, Intent intent) { Log.d(TAG_LOG, "onReceive"); String action = intent.getAction(); // perform notification action: immediately // delete intent: after 7~8sec. if (action.equals(action_positive) | action.equals(action_negative) | action.equals(action_delete)){ Log.d(TAG_LOG, "get action: " + action); //get notification uid byte[] _uid = intent.getByteArrayExtra(extra_uid); for(int i = 0; i < _uid.length; i++) { Log.d(TAG_LOG, "@@[email protected]@ :: " + Integer.toHexString(_uid[i])); } Log.d(TAG_LOG, "*+*+*++*+*+*+*+*+*+*+*+*+"); // set action id byte _action_id = 0x00; if(action.equals(action_negative) | action.equals(action_delete)) { _action_id = (byte) 0x01; } try { Log.d(TAG_LOG, "get notify"); // perform notification action value setting. byte[] get_notification_attribute = { (byte)0x02, //UID _uid[0], _uid[1], _uid[2], _uid[3], //action _action_id }; BluetoothGattService service = bluetooth_gatt.getService(UUID.fromString(service_ancs)); if (service == null) { Log.d(TAG_LOG, "cant find service @ BR"); } else { Log.d(TAG_LOG, "find service @ BR"); BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(characteristics_control_point)); if (characteristic == null) { Log.d(TAG_LOG, "cant find chara @ BR"); } else { Log.d(TAG_LOG, "find chara @ BR"); characteristic.setValue(get_notification_attribute); bluetooth_gatt.writeCharacteristic(characteristic); } } }catch(ArrayIndexOutOfBoundsException e){ Log.d(TAG_LOG, "error"); e.printStackTrace(); } Log.d(TAG_LOG, "onReceive"); }else if(action.equals(action_set_clock)) { }else if(action.equals(action_renotify)) { Log.d(TAG_LOG, "action_renotify"); //music control notification Intent __intent = new Intent(getApplicationContext(), MusicControlActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, __intent, 0); Intent _intent_delete = new Intent(); _intent_delete.setAction(action_renotify); PendingIntent _delete_action = PendingIntent.getBroadcast(getApplicationContext(), notification_id, _intent_delete, PendingIntent.FLAG_ONE_SHOT); Notification.Builder notificationBuilder = new Notification.Builder(getApplicationContext()) .setSmallIcon(R.drawable.whatsapp) .setContentTitle("music💿") .setContentIntent(pendingIntent) .addAction(R.drawable.resume, "Controller Open", pendingIntent) .setLocalOnly(true) .setPriority(Notification.PRIORITY_MIN) .setDeleteIntent(_delete_action) .extend(new Notification.WearableExtender().setContentAction(0).setHintHideIcon(true)) ; Notification _notification = notificationBuilder.build(); // _notification.flags = _notification.flags | Notification.FLAG_ONGOING_EVENT; NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notificationManager.notify(id_music_control, _notification); notification_id++; } } } }