package com.rftransceiver.activity; import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.brige.blutooth.le.BluetoothLeService; import com.my_interface.SendMessageListener; import com.rftransceiver.R; import com.rftransceiver.adapter.ListConversationAdapter; import com.rftransceiver.datasets.ConversationData; import com.rftransceiver.util.Constants; import com.source.DataPacketOptions; import com.source.parse.ParseFactory; import com.source.sounds.Audio_Reciver; import com.source.sounds.Audio_Recorder; import com.source.sounds.SoundsEntity; import com.source.text.TextEntity; import butterknife.ButterKnife; import butterknife.InjectView; public class MainActivity extends ActionBarActivity implements View.OnClickListener, SearchActivity.Connectlistener,SendMessageListener{ @InjectView(R.id.listview_conversation) ListView listView; @InjectView(R.id.et_send_message) EditText etSendMessage; @InjectView(R.id.btn_send) Button btnSend; @InjectView(R.id.btn_sounds) Button btnSounds; @InjectView(R.id.tv_current_channel) TextView tvChannel; @InjectView(R.id.tv_current_style) TextView tvStyle; private Handler dataExchangeHandler = null; //exchange data with work thread private final String TAG = getClass().getSimpleName(); private ListConversationAdapter conversationAdapter = null; //the adapter of listView private TextEntity textEntity; //the text entity to decide how packet text data to be sent private Audio_Recorder record; //the recorder to record sounds and send private Audio_Reciver receiver; //handle the received sounds data---to play theme private ParseFactory parseFactory; //manage how to parse received packeted data private boolean receiveError = false; //mark have received a error packet or not private boolean canWrite = false; private BluetoothLeService bluetoothLeService; //ble connection controller private boolean leServiceBind = false; //mark weather bind leService or not private ServiceConnection mServiceConnection = null; // Code to manage Service lifecycle. private boolean bleConnected = false; private boolean bluetoothConnected = false; private String deviceName = 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(); if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { bleConnected = true; setTitle(getString(R.string.connected, deviceName)); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { bleConnected = false; setTitle(getString(R.string.disconnected, "")); }else if(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { canWrite = true; } } }; public volatile static boolean changeChannel = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //initUsb(); System.loadLibrary("speex"); initViews(); //open bluetooth and start bluetooth sever openBluetooth(); initDataExchangeHandler(); //initial the receiver receiver = new Audio_Reciver(); DataPacketOptions soundsOptions = new DataPacketOptions(DataPacketOptions.Data_Type_InOptions.sounds, 5); SoundsEntity soundsEntity = new SoundsEntity(); soundsEntity.setOptions(soundsOptions); soundsEntity.setSendListener(this); //initial the recorder record = new Audio_Recorder(); record.setSoundsEntity(soundsEntity); //initial the text entity textEntity = new TextEntity(); DataPacketOptions textOptions = new DataPacketOptions(DataPacketOptions.Data_Type_InOptions.text, 5); textEntity.setOptions(textOptions); textEntity.setSendListener(this); //initial parseFactory parseFactory = new ParseFactory(); parseFactory.setHandler(dataExchangeHandler); parseFactory.setSoundsOptions(soundsOptions); parseFactory.setTextOptions(textOptions); soundsOptions = null; textOptions = null; //startReceive(); updateChannel(getString(R.string.channel_1)); initBLETool(); } private void initDataExchangeHandler() { dataExchangeHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case Constants.MSG_WHAT_STATE: switch (msg.arg1) { case 0: setTitle(getString(R.string.bluetooth_none_connection)); bluetoothConnected = false; break; case 1: setTitle(getString(R.string.bluetooth_listening)); break; case 2: setTitle(getString(R.string.bluetooth_connecting)); break; case 3: setTitle(getString(R.string.bluetooth_connected)); bluetoothConnected = true; break; } break; case Constants.MESSAGE_READ: switch (msg.arg1) { case 0: switch (msg.arg2) { case 0: //start to receive sounds data receiver.startReceiver(); btnSounds.setText(getString(R.string.sounds_im)); btnSounds.setClickable(false); break; case 1: //end to receive sounds data receiver.stopReceiver(); btnSounds.setText(getString(R.string.record_sound)); btnSounds.setClickable(true); break; case 2: //cache the received sounds data receiveError = false; byte[] sound = (byte[]) msg.obj; receiver.cacheData(sound,Constants.Small_Sounds_Packet_Length); break; } break; case 1: //receive text data byte[] data = (byte[]) msg.obj; ConversationData text = new ConversationData(); text.setContent(new String(data)); text.setConversationType(ListConversationAdapter.ConversationType.Other); conversationAdapter.addData(text); break; case 2: switch (msg.arg2) { case 0: updateChannel(getString(R.string.channel_1)); break; case 1: updateChannel(getString(R.string.channel_2)); break; case 2: updateChannel(getString(R.string.channel_3)); break; case 3: updateChannel(getString(R.string.channel_4)); break; } break; case 3: if(!receiveError) { showToast(getString(R.string.received_error_packet)); } //the packet is wrong receiveError = true; break; } break; case Constants.MESSAGE_WRITE: break; case Constants.MESSAGE_TOAST: showToast(msg.getData().getString(Constants.TOAST)); break; } } }; } private void initBLETool() { if(mServiceConnection == null) { mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder service) { bluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); bluetoothLeService.setSendMessageListener(MainActivity.this); if (!bluetoothLeService.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth"); finish(); } leServiceBind = true; } @Override public void onServiceDisconnected(ComponentName componentName) { bluetoothLeService.setSendMessageListener(null); bluetoothLeService = null; leServiceBind = false; } }; } if(!leServiceBind) { Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); } } //update the channel in UI private void updateChannel(String channel) { try { tvChannel.setText(getString(R.string.channel_label,channel)); } catch (NullPointerException e) { e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main,menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_close_device: //close connection closeConnection(); return true; case R.id.action_connect_device: //open a dialogFragment to discover and pair a bluetooth device SearchActivity.connectlistener = MainActivity.this; startActivity(new Intent(MainActivity.this,SearchActivity.class)); return true; case R.id.action_clear: conversationAdapter.clear(); return true; case R.id.action_reset_scm: if(canWrite) { receiver.stopReceiver(); record.stopRecording(); receiver.clear(); parseFactory.resetSounds(); btnSounds.setText(getString(R.string.record_sound)); bluetoothLeService.write(Constants.Reset,false); updateChannel(getString(R.string.channel_1)); }else { showToast(getString(R.string.not_connect_device)); } return true; case R.id.action_choose_channel: if(!canWrite) { showToast(getString(R.string.not_connect_device)); return false; } chooseChannel(); return true; } return false; } //close a bluetooth connection private void closeConnection() { if(bluetoothLeService != null) { bluetoothLeService.disconnect(); } } //choose or change channel private void chooseChannel() { new AlertDialog.Builder(this) .setTitle(getString(R.string.choose_channel)) .setIcon(android.R.drawable.ic_dialog_info) .setSingleChoiceItems(new String[] {getString(R.string.channel_1), getString(R.string.channel_2), getString(R.string.channel_3), getString(R.string.channel_4)}, 0, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { changeChanel((byte)which); dialog.dismiss(); } } ) .setNegativeButton("取消", null) .show(); } private void changeChanel(byte tail) { byte[] chanel = new byte[Constants.Packet_Length]; chanel[0] = Constants.Packet_Head; chanel[Constants.Packet_Length-2] = tail; chanel[Constants.Packet_Length-1] = Constants.Packet_Channel_Tail; bluetoothLeService.write(chanel,false); changeChannel = true; chanel = null; } private final BroadcastReceiver bluetoothSate = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,-1); switch (state) { case BluetoothAdapter.STATE_OFF: showToast(getString(R.string.bluetooth_closed)); if(bluetoothLeService != null) { bluetoothLeService.disconnect(); } break; case BluetoothAdapter.STATE_ON: break; } } } }; @Override protected void onResume() { super.onResume(); registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); registerReceiver(bluetoothSate, new IntentFilter(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)); } @Override protected void onPause() { super.onPause(); unregisterReceiver(mGattUpdateReceiver); unregisterReceiver(bluetoothSate); } @Override protected void onDestroy() { super.onDestroy(); parseFactory = null; record.stopRecording(); receiver.stopReceiver(); textEntity.setSendListener(null); textEntity.setOptions(null); record = null; receiver = null; textEntity = null; if(leServiceBind) { unbindService(mServiceConnection); bluetoothLeService = null; } } //open the bluetooth private void openBluetooth() { final BluetoothAdapter bluetoothAdapter; // 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); bluetoothAdapter = bluetoothManager.getAdapter(); //check this device weather support bluetooth or not //if support then enable the bluetooth if(bluetoothAdapter != null) { if(!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivity(enableBtIntent); } }else { showToast(getString(R.string.device_bluetooth_not_support)); finish(); } } private void initViews() { ButterKnife.inject(this); btnSend.setOnClickListener(this); conversationAdapter = new ListConversationAdapter(this); listView.setAdapter(conversationAdapter); btnSounds.setOnClickListener(this); tvChannel.setText(getString(R.string.channel_label, getString(R.string.channel_1))); tvStyle.setText(getString(R.string.style_label, getString(R.string.blue_sytle_ble))); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_send: if(!canWrite) { showToast(getString(R.string.not_connect_device)); return; } if(receiver.isReceive()){ showToast(getString(R.string.cannot_send)); return; } btnSend.setClickable(false); String sendContent = etSendMessage.getText().toString(); etSendMessage.setText(""); if(TextUtils.isEmpty(sendContent)) { return; } textEntity.unpacking(sendContent); hideInputSoft(); ConversationData data = new ConversationData(); data.setContent(sendContent); data.setConversationType(ListConversationAdapter.ConversationType.Me); conversationAdapter.addData(data); data = null; btnSend.setClickable(true); break; case R.id.btn_sounds: if(btnSounds.getText().equals(getString(R.string.record_sound))) { if(!canWrite){ showToast(getString(R.string.not_connect_device)); return; } if(receiver.isReceive()){ showToast(getString(R.string.cannot_send)); return; } //start record record.startRecording(); btnSounds.setText(getString(R.string.recording_sound)); } else if(btnSounds.getText().equals(getString(R.string.recording_sound))) { //stop recording record.stopRecording(); btnSounds.setText(getString(R.string.record_sound)); } break; default: break; } } private void hideInputSoft() { //InputMethodManager im = getSystemService(INPUT_METHOD_SERVICE); } @Override public void startConnect(BluetoothDevice device) { deviceName = device.getName(); if(bluetoothLeService != null) { bluetoothLeService.connect(device.getAddress()); } } private void showToast(final String s) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show(); } }); } @Override public void sendPacketedData (byte[] data,boolean end){ if(data == null) return; if(canWrite) { bluetoothLeService.write(data,true); } data = null; } @Override public void sendUnPacketedData(byte[] data,int mode) { switch (mode) { case 0: receiveError = false; //correct data if(data != null) { parseFactory.sendToRelativeParser(data); } return; case 1: //wrong data if(!receiveError) { showToast(getString(R.string.received_error_packet)); } receiveError = true; return; case 2: //send failed showToast(getString(R.string.send_failed)); break; } } 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_AVAILABLE); return intentFilter; } }