package info.guardianproject.securereaderinterface.installer; import info.guardianproject.securereaderinterface.R; import info.guardianproject.securereader.SocialReader; import info.guardianproject.securereaderinterface.App; import info.guardianproject.securereaderinterface.FragmentActivityWithMenu; import info.guardianproject.securereaderinterface.installer.SecureBluetooth.SecureBluetoothEventListener; import info.guardianproject.securereaderinterface.views.StoryItemPageView; import info.guardianproject.iocipher.File; import info.guardianproject.iocipher.FileInputStream; import java.io.BufferedInputStream; import java.io.FileNotFoundException; import java.io.IOException; import org.holoeverywhere.widget.ProgressBar; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.tinymission.rss.Item; public class SecureBluetoothSenderActivity extends FragmentActivityWithMenu implements OnClickListener, SecureBluetoothEventListener, OnItemClickListener { public static final String LOGTAG = "SecureBluetoothSenderActivity"; private enum UIState { Scanning, Sending, SentOk }; SecureBluetooth sb; TextView sendTextView; View mLLScan; View mLLSend; View mLLSharedStory; Button sendButton; View scanButton; View ivScanning; TextView tvScanning; ArrayAdapter<DeviceInfo> mNewDevicesArrayAdapter; ListView newDevicesListView; Intent shareIntent; File fileToSend; long itemIdToSend; Item mItemSent; UIState mCurrentState = UIState.Scanning; ProgressBar mProgressSend; @Override public void onCreate(Bundle savedInstanceState) { // this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); super.onCreate(savedInstanceState); // Display home as up setDisplayHomeAsUp(true); setMenuIdentifier(R.menu.activity_bluetooth_sender); // Pull out the item id shareIntent = this.getIntent(); if (shareIntent.hasExtra(SocialReader.SHARE_ITEM_ID)) { SocialReader socialReader = ((App) this.getApplication()).socialReader; itemIdToSend = shareIntent.getLongExtra(SocialReader.SHARE_ITEM_ID, Item.DEFAULT_DATABASE_ID); fileToSend = socialReader.packageItem(itemIdToSend); mItemSent = socialReader.getItemFromId(itemIdToSend); } else { Log.e(LOGTAG, "No Item Id to Share"); finish(); } setContentView(R.layout.activity_secure_blue_tooth_sender); setActionBarTitle(getString(R.string.title_activity_secure_blue_tooth_sender)); sb = new SecureBluetooth(); sb.setSecureBluetoothEventListener(this); sb.enableBluetooth(this); mLLScan = findViewById(R.id.llScan); mLLSend = findViewById(R.id.llSend); mLLSharedStory = findViewById(R.id.llSharedStory); // Initialize array adapters. One for already paired devices and one for // newly discovered devices mNewDevicesArrayAdapter = new ArrayAdapter<DeviceInfo>(this, R.layout.activity_secure_blue_tooth_sender_device_name); // Find and set up the ListView for newly discovered devices newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(this); sendTextView = (TextView) this.findViewById(R.id.btSendText); sendTextView.setText("Click Scan to view the available devices"); sendButton = (Button) this.findViewById(R.id.btSendButton); //sendButton.setVisibility(View.INVISIBLE); sendButton.setEnabled(false); sendButton.setOnClickListener(this); mProgressSend = (ProgressBar) findViewById(R.id.progressSend); scanButton = findViewById(R.id.btScanButton); scanButton.setEnabled(true); scanButton.setOnClickListener(this); ivScanning = findViewById(R.id.ivScanning); tvScanning = (TextView) findViewById(R.id.tvScanning); mLLSharedStory.findViewById(R.id.btnClose).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Go back to what we were doing... finish(); } }); showScanningSpinner(false); } private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // If it's already paired, skip it, because it's been listed // already // if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter.add(new DeviceInfo(device.getName(), device.getAddress())); // } // When discovery is finished, change the Activity title } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false); // setTitle(R.string.select_device); if (mNewDevicesArrayAdapter.getCount() == 0) { // String noDevices = // getResources().getText(R.string.none_found).toString(); mNewDevicesArrayAdapter.add(new DeviceInfo(getString(R.string.bluetooth_no_devices_found), null)); } showScanningSpinner(false); } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { setProgressBarIndeterminateVisibility(true); showScanningSpinner(true); } } }; @Override protected void onResume() { super.onResume(); // Register for broadcasts when a device is discovered IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); // Register for broadcasts when discovery has finished filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(receiver, filter); // Register for broadcasts when discovery has started filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED); registerReceiver(receiver, filter); updateUi(); // Start a scan automatically if (mCurrentState == UIState.Scanning) scanButton.performClick(); } private void updateUi() { if (mCurrentState == UIState.Scanning) { mLLScan.setVisibility(View.VISIBLE); mLLSend.setVisibility(View.GONE); mLLSharedStory.setVisibility(View.GONE); newDevicesListView.setOnItemClickListener(this); } else if (mCurrentState == UIState.Sending) { mLLScan.setVisibility(View.GONE); mLLSend.setVisibility(View.VISIBLE); mLLSharedStory.setVisibility(View.GONE); } else if (mCurrentState == UIState.SentOk) { mLLScan.setVisibility(View.GONE); mLLSend.setVisibility(View.GONE); StoryItemPageView storyView = (StoryItemPageView) mLLSharedStory.findViewById(R.id.sharedItemView); storyView.populateWithItem(mItemSent); storyView.loadMedia(null); mLLSharedStory.setVisibility(View.VISIBLE); } } private void setUiState(UIState state) { mCurrentState = state; updateUi(); } @Override public void onPause() { Log.v(LOGTAG,"onPause"); super.onPause(); } @Override protected void onStop() { Log.v(LOGTAG,"onStop"); if (sb.btAdapter.isDiscovering()) { sb.btAdapter.cancelDiscovery(); } sb.disconnect(); showScanningSpinner(false); unregisterReceiver(receiver); super.onStop(); } private void setStatusText(final int idText) { sendTextView.post(new Runnable() { @Override public void run() { sendTextView.setText(idText); } }); } /* public void onClick(View clickedView) { if (clickedView == sendButton) { //sb.write("Hello Receiver, this is sender sending"); //sb.disconnect(); if (fileToSend != null) { try { // For debuggging FileInputStream fis = new FileInputStream(fileToSend); BufferedInputStream bis = new BufferedInputStream( fis ); ObjectInputStream input = new ObjectInputStream ( bis ); //Deserialize it try { Item inItem = (Item) input.readObject(); if (inItem != null) { Log.v(LOGTAG,"We packaged an Item!!!: " + inItem.toString()); } sb.writeObject(inItem); Log.v(LOGTAG,"We sent an Item!!!: " + inItem.toString()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); */ private void sendFile() { if (fileToSend != null) { BufferedInputStream bin = null; try { long lengthTotal = fileToSend.length(); long lengthSent = 0; updateSendProgress(0, lengthTotal); // First send size sb.writeLength(lengthTotal); bin = new BufferedInputStream(new FileInputStream(fileToSend)); byte[] buffer = new byte[256]; int bytesRead; while ((bytesRead = bin.read(buffer)) != -1) { sb.write(buffer); lengthSent += bytesRead; updateSendProgress(lengthSent, lengthTotal); Log.v(LOGTAG,"bytes sent now: " + bytesRead + " " + lengthSent + " total: " + lengthTotal); } setStatusText(R.string.bluetooth_send_sent_item); setUiState(UIState.SentOk); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); setStatusText(R.string.bluetooth_send_error); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); setStatusText(R.string.bluetooth_send_error); } finally { if (bin != null) { try { bin.close(); } catch (IOException e) { } } //sb.disconnect(); } } else { sendTextView.setText("Error Sending Item"); } } @Override public void onClick(View clickedView) { if (clickedView == sendButton) { // sb.write("Hello Receiver, this is sender sending"); // sb.disconnect(); sendFile(); sendButton.setEnabled(false); } else if (clickedView == scanButton) { mNewDevicesArrayAdapter.clear(); showScanningSpinner(true); sb.startDiscovery(); } } @Override public void onItemClick(AdapterView<?> av, View v, int position, long arg3) { // Cancel discovery because it's costly and we're about to connect sb.btAdapter.cancelDiscovery(); showScanningSpinner(false); // Get the device MAC address DeviceInfo info = (DeviceInfo) av.getAdapter().getItem(position); if (info != null) { setUiState(UIState.Sending); String address = info.getAddress(); setStatusText(R.string.bluetooth_send_connecting); // Remove onitemclicklistener newDevicesListView.setOnItemClickListener(null); // Connect v.post(new Runnable() { private String mAddress; @Override public void run() { if (!sb.connect(mAddress)) { setUiState(UIState.Scanning); Toast.makeText(SecureBluetoothSenderActivity.this, R.string.bluetooth_send_connect_error, Toast.LENGTH_LONG).show(); } } public Runnable init(String address) { mAddress = address; return this; } }.init(address)); } } @Override public void secureBluetoothEvent(int eventType, int dataLength, Object data) { Log.v(LOGTAG, "secureBluetoothEvent " + eventType); if (eventType == SecureBluetooth.EVENT_CONNECTED) { Log.v(LOGTAG, "Connected"); setStatusText(R.string.bluetooth_send_connected); sendButton.setEnabled(true); onClick(sendButton); //sendFile(); } else if (eventType == SecureBluetooth.EVENT_DISCONNECTED) { Log.v(LOGTAG, "Disconnected"); setStatusText(R.string.bluetooth_send_disconnected); sendButton.setEnabled(true); } } private void showScanningSpinner(boolean show) { if (show) { tvScanning.setText(R.string.bluetooth_send_scanning); ivScanning.setVisibility(View.VISIBLE); ivScanning.startAnimation(AnimationUtils.loadAnimation(this, R.anim.rotate)); scanButton.setEnabled(false); } else { tvScanning.setText(R.string.bluetooth_send_scan); ivScanning.clearAnimation(); ivScanning.setVisibility(View.GONE); scanButton.setEnabled(true); } } private void updateSendProgress(long lengthSent, long max) { mProgressSend.setMax((int) max); mProgressSend.setProgress((int) lengthSent); mProgressSend.invalidate(); } private class DeviceInfo { private final String name; private final String address; public DeviceInfo(String name, String address) { this.name = name; this.address = address; } public String getName() { return name; } public String getAddress() { return address; } @Override public String toString() { return getName(); } } @Override protected void onUnlockedActivityResult(int requestCode, int resultCode, Intent data) { super.onUnlockedActivityResult(requestCode, resultCode, data); // If we don�t allow BT to be turned on, just quit out of this activity! if (requestCode == SecureBluetooth.REQUEST_ENABLE_BT && resultCode == RESULT_CANCELED) { finish(); } } }