Java tutorial
/* * Copyright Cypress Semiconductor Corporation, 2014-2015 All rights reserved. * * This software, associated documentation and materials ("Software") is * owned by Cypress Semiconductor Corporation ("Cypress") and is * protected by and subject to worldwide patent protection (UnitedStates and foreign), * United States copyright laws and international * treaty provisions. Therefore, unless otherwise specified in a separate * license agreement between you and Cypress, this Software * must be treated like any other copyrighted material. Reproduction, * modification, translation, compilation, or representation of this * Software in any other form (e.g., paper, magnetic, optical, silicon) * is prohibited without Cypress's express written permission. * * Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY * KIND, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, * NONINFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. Cypress reserves the right to make changes * to the Software without notice. Cypress does not assume any liability * arising out of the application or use of Software or any product or * circuit described in the Software. Cypress does not authorize its * products for use as critical components in any products where a * malfunction or failure may reasonably be expected to result in * significant injury or death ("High Risk Product"). By including * Cypress's product in a High Risk Product, the manufacturer of such * system or application assumes all risk of such use and in doing so * indemnifies Cypress against all liability. * * Use of this Software may be limited by and subject to the applicable * Cypress software license agreement. * * */ package com.cypress.cysmart.RDKEmulatorView; import android.app.ProgressDialog; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageButton; import com.cypress.cysmart.BLEConnectionServices.BluetoothLeService; import com.cypress.cysmart.CommonUtils.Constants; import com.cypress.cysmart.CommonUtils.GattAttributes; import com.cypress.cysmart.CommonUtils.Logger; import com.cypress.cysmart.CommonUtils.UUIDDatabase; import com.cypress.cysmart.CommonUtils.Utils; import com.cypress.cysmart.R; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * Fragment class to show the emulator view of the Remote control RDK which has Human Interface * Device sservice */ public class RemoteControlEmulatorFragment extends Fragment { //Flags public static boolean mIsrecording = false; // GATT service and characteristics private static BluetoothGattService mservice; private final ArrayList<ReportCharacteristicDescriptionModel> charaDataModel = new ArrayList<ReportCharacteristicDescriptionModel>(); // Handler flag private boolean HANDLER_FLAG = true; private boolean mNotiificationsEnabled = false; //UI Elements private ProgressDialog mProgressDialog; //Remote control emulator buttons private ImageButton mVolumePlusbtn; private ImageButton mVolumeMinusBtn; private ImageButton mChannelPlusBtn; private ImageButton mChannelMinusBtn; private ImageButton mLeftBtn; private ImageButton mRightBtn; private ImageButton mBackBtn; private ImageButton mGesturebtn; private ImageButton mExitBtn; private ImageButton mPowerBtn; private ImageButton mRecBtn; //PCM data private byte[] mPCMData; //Constants private int SAMPLE_RATE = 16000; private int BUFFER_SIZE = 8000; private int HANDLER_DELAY = 1500; //AudioTrack private AudioTrack mAudioTrack; /** * BroadcastReceiver for receiving the GATT server status */ private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); Bundle extras = intent.getExtras(); // GATT Data available if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { /** * Byte information send through BLE received here */ if (extras.containsKey(Constants.EXTRA_BYTE_VALUE)) { byte[] array = intent.getByteArrayExtra(Constants.EXTRA_BYTE_VALUE); /** * Converting the received voice data to HEX value * Update the value in the UI */ String hexValue = getHexValue(array); updateEmulatorView(hexValue); /** * Report reference descriptor received */ if (extras.containsKey(Constants.EXTRA_DESCRIPTOR_REPORT_REFERENCE_ID)) { String reportReference = intent .getStringExtra(Constants.EXTRA_DESCRIPTOR_REPORT_REFERENCE_ID); /** * Audio report reference control received */ if (reportReference .equalsIgnoreCase(ReportAttributes.AUDIO_REPORT_REFERENCE_CONTROL_STRING)) { /** * Extracting the first byte to verify * sync is required */ String firstByte = hexValue.substring(0, 2); if (firstByte.equalsIgnoreCase(ReportAttributes.MICROPHONE_SYNC)) { /** * Sync required * Updating the ADPCMStateModel values */ if (hexValue.length() == 8) { ADPCMStateModel.prevIndex = array[1]; ADPCMStateModel.prevSample = ((int) array[2] << 8); ADPCMStateModel.prevSample |= array[3]; } } } /** * Audio report reference data received */ if (reportReference.equalsIgnoreCase(ReportAttributes.AUDIO_REPORT_REFERENCE_DATA_STRING)) { /** * Getting the converted PCM Data * writing the byte data to AudioTrack class */ mPCMData = ADPCMConverter.getPCMData(array); mAudioTrack.write(mPCMData, 0, mPCMData.length); if (mIsrecording) { createPCMFile(mPCMData); } } } } } /** * Bonding Action is in Process * Update the GUI with a Progress dialog * during bonding */ if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR); if (state == BluetoothDevice.BOND_BONDING) { // Bonding... Utils.bondingProgressDialog(getActivity(), mProgressDialog, true); } else if (state == BluetoothDevice.BOND_BONDED) { String dataLog = getResources().getString(R.string.dl_commaseparator) + "[" + BluetoothLeService.getmBluetoothDeviceName() + "|" + BluetoothLeService.getmBluetoothDeviceAddress() + "]" + getResources().getString(R.string.dl_commaseparator) + getResources().getString(R.string.dl_connection_paired); Logger.datalog(dataLog); Utils.bondingProgressDialog(getActivity(), mProgressDialog, false); getAllCharacteristicReportReference(); } else if (state == BluetoothDevice.BOND_NONE) { String dataLog = getResources().getString(R.string.dl_commaseparator) + "[" + BluetoothLeService.getmBluetoothDeviceName() + "|" + BluetoothLeService.getmBluetoothDeviceAddress() + "]" + getResources().getString(R.string.dl_commaseparator) + getResources().getString(R.string.dl_connection_unpaired); Logger.datalog(dataLog); } } } }; //View private View mParentView; /** * Constructor * * @param bluetoothGattService * @return RemoteControlEmulatorService */ public RemoteControlEmulatorFragment create(BluetoothGattService bluetoothGattService) { mservice = bluetoothGattService; RemoteControlEmulatorFragment remoteControlEmulatorFragment = new RemoteControlEmulatorFragment(); return remoteControlEmulatorFragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { /** * Getting the current orientation of the screen * Loading different view for LandScape and portrait */ int currentOrientation = getResources().getConfiguration().orientation; if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) { mParentView = inflater.inflate(R.layout.rdk_emulator_view_landscape, container, false); } else { mParentView = inflater.inflate(R.layout.rdk_emulator_view_portrait, container, false); } mProgressDialog = new ProgressDialog(getActivity()); /** * Getting the ID's of all Emulator view UI elements */ Button mTrackpadView = (Button) mParentView.findViewById(R.id.trackpad_btn); Button mMicrophoneView = (Button) mParentView.findViewById(R.id.microphone_btn); mVolumePlusbtn = (ImageButton) mParentView.findViewById(R.id.volume_plus_btn); mVolumeMinusBtn = (ImageButton) mParentView.findViewById(R.id.volume_minus_btn); mChannelPlusBtn = (ImageButton) mParentView.findViewById(R.id.channel_plus_btn); mChannelMinusBtn = (ImageButton) mParentView.findViewById(R.id.channel_minus_btn); mLeftBtn = (ImageButton) mParentView.findViewById(R.id.left_btn); mRightBtn = (ImageButton) mParentView.findViewById(R.id.right_btn); mBackBtn = (ImageButton) mParentView.findViewById(R.id.back_btn); mGesturebtn = (ImageButton) mParentView.findViewById(R.id.gesture_btn); mExitBtn = (ImageButton) mParentView.findViewById(R.id.exit_btn); mPowerBtn = (ImageButton) mParentView.findViewById(R.id.power_btn); mRecBtn = (ImageButton) mParentView.findViewById(R.id.record_btn); mRecBtn = (ImageButton) mParentView.findViewById(R.id.record_btn); /** * AudioTrack class initialisation as follows * streamType- AudioManager.STREAM_MUSIC, * sampleRateInHz- 16000, * channelConfig- AudioFormat.CHANNEL_OUT_MONO, * audioFormat-AudioFormat.ENCODING_PCM_16BIT, * bufferSizeInBytes-8000, * mode- AudioTrack.MODE_STREAM * */ mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE, AudioTrack.MODE_STREAM); /** * TrackPAd button click listner */ mTrackpadView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { TrackpadEmulatorFragment trackpadService = new TrackpadEmulatorFragment(); try { displayView(trackpadService); } catch (Exception e) { e.printStackTrace(); } } }); /** * Microphone Button click listner */ mMicrophoneView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { MicrophoneEmulatorFragment microphoneService = new MicrophoneEmulatorFragment(); microphoneService.create(mservice); displayView(microphoneService); } }); return mParentView; } @Override public void onResume() { super.onResume(); HANDLER_FLAG = true; Utils.setUpActionBar(getActivity(), getResources().getString(R.string.rdk_emulator_view)); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); getActivity().registerReceiver(mGattUpdateReceiver, intentFilter); initializeBondingIFnotBonded(); } @Override public void onPause() { HANDLER_FLAG = false; super.onPause(); } @Override public void onDestroy() { mNotiificationsEnabled = false; stopBroadcastAllNotifications(); getActivity().unregisterReceiver(mGattUpdateReceiver); super.onDestroy(); } private void initializeBondingIFnotBonded() { Logger.i("Bonding check"); final BluetoothDevice device = BluetoothLeService.mBluetoothAdapter .getRemoteDevice(BluetoothLeService.getmBluetoothDeviceAddress()); if (!BluetoothLeService.getBondedState()) { pairDevice(device); } else if (!mNotiificationsEnabled) { getAllCharacteristicReportReference(); } } //For Pairing private void pairDevice(BluetoothDevice device) { try { Method m = device.getClass().getMethod("createBond", (Class[]) null); m.invoke(device, (Object[]) null); } catch (Exception e) { e.printStackTrace(); } } /** * Method to get all Characteristic with report reference */ private void getAllCharacteristicReportReference() { List<BluetoothGattCharacteristic> gattCharacteristics = mservice.getCharacteristics(); charaDataModel.clear(); for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { String uuidchara = gattCharacteristic.getUuid().toString(); if (uuidchara.equalsIgnoreCase(GattAttributes.REP0RT)) { ReportCharacteristicDescriptionModel data = new ReportCharacteristicDescriptionModel( gattCharacteristic, gattCharacteristic.getInstanceId()); charaDataModel.add(data); } } prepareBroadcastAllNotifications(); } /** * prepare notifications of all Report characteristic found from the service */ private void prepareBroadcastAllNotifications() { mProgressDialog.setTitle(getResources().getString(R.string.alert_message_prepare_title)); mProgressDialog.setMessage(getResources().getString(R.string.alert_message_prepare_message) + "\n" + getResources().getString(R.string.alert_message_wait)); mProgressDialog.setCancelable(false); mProgressDialog.show(); for (int pos = 0; pos < charaDataModel.size(); pos++) { final BluetoothGattCharacteristic characteristic = charaDataModel.get(pos).getmGattCharacteristic(); if (characteristic.getDescriptor(UUIDDatabase.UUID_REPORT_REFERENCE) != null) { new Handler().postDelayed(new Runnable() { @Override public void run() { if (HANDLER_FLAG) { BluetoothLeService.setCharacteristicNotification(characteristic, true); } } }, HANDLER_DELAY * pos); } } new Handler().postDelayed(new Runnable() { @Override public void run() { if (HANDLER_FLAG) { mProgressDialog.dismiss(); getActivity().registerReceiver(mGattUpdateReceiver, Utils.makeGattUpdateIntentFilter()); mNotiificationsEnabled = true; } } }, HANDLER_DELAY * 6); } /** * stop notifications of all Report characteristc */ private void stopBroadcastAllNotifications() { List<BluetoothGattCharacteristic> gattCharacteristics = mservice.getCharacteristics(); for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { String uuidchara = gattCharacteristic.getUuid().toString(); if (uuidchara.equalsIgnoreCase(GattAttributes.REP0RT)) { final int charaProp = gattCharacteristic.getProperties(); if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { BluetoothLeService.setCharacteristicNotification(gattCharacteristic, false); } } } } /** * Method to update the GUI with the corresponding report received * * @param buttonValue */ private void updateEmulatorView(String buttonValue) { int value = ReportAttributes.lookupReportValues(buttonValue); switch (value) { case 101: mPowerBtn.setPressed(true); break; case 102: mVolumePlusbtn.setPressed(true); break; case 103: mVolumeMinusBtn.setPressed(true); break; case 104: mChannelPlusBtn.setPressed(true); break; case 105: mChannelMinusBtn.setPressed(true); break; case 106: mRecBtn.setPressed(true); mAudioTrack.play(); break; case 107: mLeftBtn.setPressed(true); break; case 108: mRightBtn.setPressed(true); break; case 109: mBackBtn.setPressed(true); break; case 110: mExitBtn.setPressed(true); break; case 201: mRecBtn.setPressed(false); mAudioTrack.stop(); break; case 202: mLeftBtn.setPressed(false); mRightBtn.setPressed(false); break; case 203: mBackBtn.setPressed(false); break; default: mPowerBtn.setPressed(false); mVolumePlusbtn.setPressed(false); mVolumeMinusBtn.setPressed(false); mChannelPlusBtn.setPressed(false); mChannelMinusBtn.setPressed(false); mLeftBtn.setPressed(false); mRightBtn.setPressed(false); mBackBtn.setPressed(false); mExitBtn.setPressed(false); break; } } private String getHexValue(byte[] array) { StringBuffer sb = new StringBuffer(); for (byte byteChar : array) { sb.append(String.format("%02x", byteChar)); } return "" + sb; } /** * Used for replacing the main content of the view with provided fragments * * @param fragment */ void displayView(Fragment fragment) { FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().add(R.id.container, fragment).addToBackStack(null).commit(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { LayoutInflater inflater = (LayoutInflater) getActivity() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mParentView = inflater.inflate(R.layout.rgb_view_landscape, null); ViewGroup rootViewG = (ViewGroup) getView(); // Remove all the existing views from the root view. try { assert rootViewG != null; rootViewG.removeAllViews(); rootViewG.addView(mParentView); } catch (Exception e) { e.printStackTrace(); } } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { LayoutInflater inflater = (LayoutInflater) getActivity() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mParentView = inflater.inflate(R.layout.rgb_view_portrait, null); ViewGroup rootViewG = (ViewGroup) getView(); // Remove all the existing views from the root view. try { assert rootViewG != null; rootViewG.removeAllViews(); rootViewG.addView(mParentView); } catch (Exception e) { e.printStackTrace(); } } } void createPCMFile(byte[] data) { String filename = MicrophoneEmulatorFragment.mfilePCM; FileOutputStream output; try { output = new FileOutputStream(filename, true); output.write(data); output.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }