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.MainActivity; import info.guardianproject.securereaderinterface.models.FeedFilterType; import info.guardianproject.securereaderinterface.views.StoryItemPageView; import info.guardianproject.iocipher.File; import info.guardianproject.iocipher.FileOutputStream; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.holoeverywhere.widget.ProgressBar; import android.bluetooth.BluetoothAdapter; 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.widget.Button; import android.widget.TextView; import com.tinymission.rss.Feed; import com.tinymission.rss.Item; import com.tinymission.rss.MediaContent; public class SecureBluetoothReceiverActivity extends FragmentActivityWithMenu implements OnClickListener, SecureBluetooth.SecureBluetoothEventListener { public static final String LOGTAG = "SecureBluetoothReceiverActivity"; private enum UIState { Listening, Receiving, ReceivedOk }; Button receiveButton; TextView receiveText; SecureBluetooth sb; java.io.File receivedContentBundleFile; BufferedOutputStream bos; boolean readyToReceive = false; private View mLLWait; private View mLLReceive; private View mLLSharedStory; UIState mCurrentState = UIState.Listening; private ProgressBar mProgressReceive; private Item mItemReceived; private long bytesReceived = 0; private boolean mReceiverRegistered; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setMenuIdentifier(R.menu.activity_bluetooth_receiver); setContentView(R.layout.activity_secure_blue_tooth_receiver); setActionBarTitle(getString(R.string.title_activity_secure_blue_tooth_receiver)); sb = new SecureBluetooth(); sb.setSecureBluetoothEventListener(this); sb.enableBluetooth(this); mLLWait = findViewById(R.id.llWait); mLLReceive = findViewById(R.id.llReceive); mLLSharedStory = findViewById(R.id.llSharedStory); receiveText = (TextView) this.findViewById(R.id.btReceiveText); receiveButton = (Button) this.findViewById(R.id.btReceiveButton); receiveButton.setOnClickListener(this); mProgressReceive = (ProgressBar) findViewById(R.id.progressReceive); mLLSharedStory.findViewById(R.id.btnClose).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Receive more? mItemReceived = null; setUiState(UIState.Listening); // Update according to current scan mode if (sb != null && sb.btAdapter != null) updateBasedOnScanMode(sb.btAdapter.getScanMode()); } }); mLLSharedStory.findViewById(R.id.btnRead).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mItemReceived != null) { Intent intent = new Intent(v.getContext(), MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra(MainActivity.INTENT_EXTRA_SHOW_THIS_ITEM, mItemReceived.getDatabaseId()); intent.putExtra(MainActivity.INTENT_EXTRA_SHOW_THIS_FEED, mItemReceived.getFeedId()); intent.putExtra(MainActivity.INTENT_EXTRA_SHOW_THIS_TYPE, FeedFilterType.SHARED); startActivity(intent); } } }); registerReceiver(); // Start by trying to receive if (sb.isEnabled()) receiveButton.performClick(); } @Override public void onPause() { Log.v(LOGTAG,"onPause"); super.onPause(); } @Override public void onStop() { Log.v(LOGTAG,"onStop"); sb.disconnect(); unregisterReceiver(); super.onStop(); } @Override protected void onResume() { registerReceiver(); super.onResume(); updateUi(); } private void updateUi() { if (mCurrentState == UIState.Receiving) { mLLReceive.setVisibility(View.VISIBLE); mLLWait.setVisibility(View.GONE); mLLSharedStory.setVisibility(View.GONE); } else if (mCurrentState == UIState.Listening) { receiveText.setText(R.string.bluetooth_receive_info); receiveButton.setEnabled(true); mLLReceive.setVisibility(View.GONE); mLLWait.setVisibility(View.VISIBLE); mLLSharedStory.setVisibility(View.GONE); } else if (mCurrentState == UIState.ReceivedOk) { mLLReceive.setVisibility(View.GONE); mLLWait.setVisibility(View.GONE); StoryItemPageView storyView = (StoryItemPageView) mLLSharedStory.findViewById(R.id.sharedItemView); storyView.populateWithItem(mItemReceived); storyView.loadMedia(null); mLLSharedStory.setVisibility(View.VISIBLE); } } private void setUiState(UIState state) { mCurrentState = state; updateUi(); } @Override public void onClick(View clickedView) { if (clickedView == receiveButton) { sb.enableDiscovery(this); sb.listen(); this.updateBasedOnScanMode(sb.btAdapter.getScanMode()); Log.v(LOGTAG, "listen called, ready to receive"); receiveButton.setEnabled(false); } } private void getReadyToReceive() { //receivedContentBundleFile = ((App) this.getApplication()).socialReader.vfsTempItemBundle(); receivedContentBundleFile = ((App) this.getApplication()).socialReader.nonVfsTempItemBundle(); receiveText.setText(getString(R.string.bluetooth_receive_connected)); try { bos = new BufferedOutputStream(new java.io.FileOutputStream(receivedContentBundleFile)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } readyToReceive = true; } @Override public void secureBluetoothEvent(int eventType, int dataLength, Object data) { Log.v(LOGTAG, "secureBluetoothEvent " + eventType); if (eventType == SecureBluetooth.EVENT_CONNECTED) { Log.v(LOGTAG, "We have a connection"); setUiState(UIState.Receiving); getReadyToReceive(); } else if (eventType == SecureBluetooth.EVENT_DISCONNECTED) { Log.v(LOGTAG, "Got a disconnect, " + bytesReceived + " bytes received"); try { bos.close(); Item receivedItem = null; ArrayList<File> mediaFiles = new ArrayList<File>(); // Now unzip it ZipFile zipFile = new ZipFile(receivedContentBundleFile); for(Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) { ZipEntry currentEntry = entries.nextElement(); if (currentEntry.getName().contains(SocialReader.CONTENT_ITEM_EXTENSION)) { InputStream inputStream = zipFile.getInputStream(currentEntry); ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); try { // Deserialize it receivedItem = (Item) objectInputStream.readObject(); objectInputStream.close(); Log.v(LOGTAG, "We have an Item!!!: " + receivedItem.getTitle()); mItemReceived = receivedItem; receivedItem.setShared(true); receivedItem.setDatabaseId(Item.DEFAULT_DATABASE_ID); receivedItem.setFeedId(Feed.DEFAULT_DATABASE_ID); for (MediaContent mc : receivedItem.getMediaContent()) { mc.setDatabaseId(MediaContent.DEFAULT_DATABASE_ID); } // Add it in.. ((App) this.getApplication()).socialReader.setItemData(receivedItem); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { // Ignore for now, we'll loop through again in a second Log.v(LOGTAG,"Ignoring media element for now"); } } if (receivedItem != null) { int mediaContentCount = 0; for(Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) { ZipEntry currentEntry = entries.nextElement(); if (currentEntry.getName().contains(SocialReader.CONTENT_ITEM_EXTENSION)) { // Ignore it, we should already have it } else { // It's Media Content // Save the files in the normal place InputStream inputStream = zipFile.getInputStream(currentEntry); BufferedOutputStream bos = null; MediaContent mediaContent = receivedItem.getMediaContent(mediaContentCount); mediaContentCount++; File savedFile = new File(((App) this.getApplication()).socialReader.getFileSystemDir(), SocialReader.MEDIA_CONTENT_FILE_PREFIX + mediaContent.getDatabaseId()); bos = new BufferedOutputStream(new FileOutputStream(savedFile)); byte buffer[] = new byte[1024]; int count; while ((count = inputStream.read(buffer)) != -1) { bos.write(buffer, 0, count); } inputStream.close(); bos.close(); } } } else { Log.e(LOGTAG,"Didn't get an item"); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (mItemReceived != null) setUiState(UIState.ReceivedOk); else setUiState(UIState.Listening); } else if (eventType == SecureBluetooth.EVENT_DATA_RECEIVED) { if (!readyToReceive) { getReadyToReceive(); } // Log.v(LOGTAG,"Reading data: " + sb.available()); Log.v(LOGTAG, "Reading data: " + dataLength); bytesReceived += dataLength; try { bos.write((byte[]) data, 0, dataLength); String textReceived = new String((byte[]) data); Log.v(LOGTAG, textReceived); updateProgress(dataLength, 2 * dataLength); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void updateProgress(final long cb, final long max) { mProgressReceive.post(new Runnable() { @Override public void run() { mProgressReceive.setMax((int) max); mProgressReceive.setProgress((int) cb); } }); } private void registerReceiver() { if (!mReceiverRegistered) { mReceiverRegistered = true; Log.d(LOGTAG, "Register receiver"); IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); registerReceiver(receiver, filter); } // Update according to current scan mode if (sb != null && sb.btAdapter != null) updateBasedOnScanMode(sb.btAdapter.getScanMode()); } private void unregisterReceiver() { if (mReceiverRegistered) { mReceiverRegistered = false; Log.d(LOGTAG, "Unregister receiver"); unregisterReceiver(receiver); } } private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent != null) { String action = intent.getAction(); if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) { int newScanMode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE); updateBasedOnScanMode(newScanMode); if (sb.isEnabled()) sb.listen(); } } } }; private void updateBasedOnScanMode(int scanMode) { if (scanMode == BluetoothAdapter.SCAN_MODE_NONE || scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) { receiveText.setVisibility(View.GONE); receiveButton.setVisibility(View.VISIBLE); } else { receiveText.setVisibility(View.VISIBLE); receiveButton.setVisibility(View.GONE); } } @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) { if (resultCode == RESULT_CANCELED) { finish(); } else if (resultCode == RESULT_OK) { receiveButton.performClick(); } } } }