package com.thisplace.mindrdr; import android.app.Activity; import android.app.FragmentTransaction; import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.content.Intent; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.media.AudioManager; import android.os.AsyncTask; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.Toast; import com.google.android.glass.media.Sounds; import com.neurosky.thinkgear.TGDevice; import com.thisplace.mindrdr.model.MindSession; import com.thisplace.mindrdr.services.MindReader; import com.thisplace.mindrdr.services.MindReaderFactory; import com.thisplace.mindrdr.model.OAuthData; import com.thisplace.mindrdr.view.CameraFlashFragment; import com.thisplace.mindrdr.view.MindReaderFragment; import com.thisplace.mindrdr.view.PhotoPreviewFragment; import com.thisplace.mindrdr.view.UploadingFragment; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import twitter4j.Status; import twitter4j.StatusUpdate; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.conf.ConfigurationBuilder; public class MindRdrActivity extends Activity { public final static String DEBUG_TAG = "MindRdrActivity"; /* if FAKE_BLUETOOTH is true then no connection attempt will be made to the mind reader and all data will be simulated. */ private static final boolean FAKE_BLUETOOTH = false; private static final boolean RAW_ENABLED = false; //ACTIVITY REQUEST CODES private static final int SPLASH_SCREEN_REQUEST_CODE = 0; private static final int OAUTH_REQUEST_CODE = 1; private static final int INTENSITY_TRIGGER = 80; private static final int INTENSITY_CANCEL_TRIGGER = 10; private static final int MIND_TAKING_PHOTO = 0; private static final int MIND_SHARING = 1; private static final int MIND_DISABLED = 2; private static final int MIND_INITIALISING = 3; private int mMindControlState = MIND_INITIALISING; BluetoothAdapter bluetoothAdapter; MindReader mindReaderService; private AudioManager mAudioManager; private Status mTwitterUpdateId = null; private MindSession mMindSession = new MindSession(); private MindReaderFragment mMindFragment; private PhotoPreviewFragment mPhotoPreviewFragment; private UploadingFragment mUploadingFragment; private CameraFlashFragment mCameraFlashFragment; private final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case TGDevice.MSG_STATE_CHANGE: switch (msg.arg1) { case TGDevice.STATE_IDLE: break; case TGDevice.STATE_CONNECTING: Log.d("DEBUG", "Connecting..."); break; case TGDevice.STATE_CONNECTED: Log.d("DEBUG", "Connected."); mindReaderService.start(); initializeCamera(); break; case TGDevice.STATE_NOT_FOUND: Log.d("DEBUG", "Can't find"); break; case TGDevice.STATE_NOT_PAIRED: Log.d("DEBUG", "not paired"); break; case TGDevice.STATE_DISCONNECTED: Log.d("DEBUG", "Disconnected mang"); } break; case TGDevice.MSG_ATTENTION: //Log.d("Intensity", Integer.toString(msg.arg1)); mMindSession.setAttention(msg.arg1); updateView(); break; case TGDevice.MSG_MEDITATION: mMindSession.setMeditation(msg.arg1); break; case TGDevice.MSG_HEART_RATE: mMindSession.setHeartRate(msg.arg1); break; default: break; } } }; private String mPhotoFile; private File mPictureFile; public PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { mPictureFile = getOutputMediaFile(); if (mPictureFile == null) { Log.d(DEBUG_TAG, "Error creating media file, check storage permissions: "); return; } try { FileOutputStream fos = new FileOutputStream(mPictureFile); fos.write(data); fos.close(); mPhotoFile = mPictureFile.getAbsolutePath(); } catch (FileNotFoundException e) { Log.d(DEBUG_TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(DEBUG_TAG, "Error accessing file: " + e.getMessage()); } releaseCamera(); showPhotoView(); } }; private Camera mCamera; private CameraPreview mPreview; private static File getOutputMediaFile() { File mediaStorageDir = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "mindrdr"); if (!mediaStorageDir.exists()) { if (!mediaStorageDir.mkdirs()) { Log.d("mindrdr", "failed to create directory"); return null; } } String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; mediaFile = new File(mediaStorageDir.getPath() + File.separator + "MindRDR" + timeStamp + ".jpg"); return mediaFile; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_mind_camera); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); Intent intent = new Intent(this, SplashActivity.class); startActivityForResult(intent,SPLASH_SCREEN_REQUEST_CODE); //initializeCamera(); //setupMindReader(); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == SPLASH_SCREEN_REQUEST_CODE) { Intent intent = new Intent(this, OAuthActivity.class); startActivityForResult(intent,OAUTH_REQUEST_CODE); }else if (requestCode == OAUTH_REQUEST_CODE) { Log.d("MindRdrActivity","OAUTH Activity Finished"); if(resultCode == RESULT_OK) { setupMindReader(); mMindFragment = MindReaderFragment.newInstance("Take Photo","Cancel"); getFragmentManager().beginTransaction() .add(R.id.fragment_container, mMindFragment).commit(); }else{ Log.d("MindRdrActivity","OAUTH Activity Failed to scan data"); } } } private void upload() { showUploadingView(); new PhotoUploaderAsyncTask().execute(mPhotoFile); } private void initializeCamera() { // Create an instance of Camera Log.d("MindRdrActivity","initialiseCamera"); if(mCamera == null){ mCamera = Camera.open(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.removeAllViews(); preview.addView(mPreview); } } private void releaseCamera() { Log.d("MindRdrActivity","releaseCamera"); if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; mPreview = null; } } private void initialiseMindReadings() { mMindSession = null; mMindSession = new MindSession(); } private void updateView() { // check we are getting good values before hiding splash if (mMindControlState == MIND_INITIALISING) { if (mMindSession.getAttention() > 0) { initialiseMindReadings(); mMindControlState = MIND_TAKING_PHOTO; } return; } if (mMindControlState != MIND_DISABLED) { mMindSession.updateMindData(); mMindFragment.updateMindReading(mMindSession.getAttention()); if (mMindSession.getAttention() >= INTENSITY_TRIGGER) { if (mMindControlState == MIND_TAKING_PHOTO) { mMindControlState = MIND_DISABLED; takePhoto(); } else if (mMindControlState == MIND_SHARING) { mMindControlState = MIND_DISABLED; if (mindReaderService != null) { mindReaderService.close(); mindReaderService = null; } upload(); } } else if (mMindSession.getAttention() <= INTENSITY_CANCEL_TRIGGER && mMindControlState == MIND_SHARING) { initializeCamera(); showTakePhotoView(); } } } private void setupMindReader() { if (FAKE_BLUETOOTH == true) { mindReaderService = MindReaderFactory.getMindReader(null, handler); handler.postDelayed((Runnable) mindReaderService, 1000); return; } bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { // Alert user that Bluetooth is not available Toast.makeText(this, "Bluetooth not available", Toast.LENGTH_LONG).show(); finish(); } else { /* create the TGDevice */ mindReaderService = MindReaderFactory.getMindReader(bluetoothAdapter, handler); mindReaderService.connect(RAW_ENABLED); } } @Override public void onDestroy() { try { if (mindReaderService != null) { mindReaderService.close(); mindReaderService = null; } releaseCamera(); } catch (NullPointerException e) { } super.onDestroy(); } @Override protected void onPause() { super.onPause(); releaseCamera(); } @Override public void onStop() { try { if (mindReaderService != null) { mindReaderService.close(); mindReaderService = null; } releaseCamera(); } catch (NullPointerException e) { } super.onStop(); } @Override public void onResume() { super.onResume(); /* if (mCamera == null) { initializeCamera(); } */ } public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { Log.d("MindRdrActivity","Back detected shutting down"); finish(); } return super.onKeyDown(keyCode, event); } private void takePhoto() { mAudioManager.playSoundEffect(Sounds.SUCCESS); mCamera.takePicture(null, null, mPicture); doCameraFlash(); } private void showPhotoView() { mPhotoPreviewFragment = PhotoPreviewFragment.newInstance(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, mPhotoPreviewFragment); transaction.commit(); new CountDownTimer(5000, 1000) { @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { showUploadView(); } }.start(); } private void showUploadView() { FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.remove(mCameraFlashFragment); transaction.commit(); mCameraFlashFragment = null; mMindFragment = MindReaderFragment.newInstance("Post to Twitter","Take another photo"); transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, mMindFragment); transaction.commit(); mMindControlState = MIND_SHARING; } private void showUploadingView() { mMindFragment.hideActionText(); mUploadingFragment = UploadingFragment.newInstance(); getFragmentManager().beginTransaction() .add(R.id.fragment_container, mUploadingFragment).commit(); } private void showSuccessView() { mUploadingFragment.showSuccess(); initializeCamera(); new CountDownTimer(5000, 1000) { @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { showTakePhotoView(); } }.start(); } private void showTakePhotoView() { mMindFragment = null; mMindFragment = MindReaderFragment.newInstance("Take Photo","Cancel"); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.remove(mUploadingFragment); mUploadingFragment = null; transaction.replace(R.id.fragment_container, mMindFragment); transaction.commit(); mMindControlState = MIND_INITIALISING; setupMindReader(); } private void doCameraFlash() { mCameraFlashFragment = CameraFlashFragment.newInstance(); getFragmentManager().beginTransaction() .add(R.id.fragment_container, mCameraFlashFragment).commit(); } private class PhotoUploaderAsyncTask extends AsyncTask<String, Integer, String> { int serverResponseCode = 0; Twitter twitter; @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(String... params) { return uploadToTwitter(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onPostExecute(String result) { super.onPostExecute(result); // uploadResult(result.toString()); showSuccessView(); } private void checkExternalMedia() { boolean mExternalStorageAvailable = false; boolean mExternalStorageWriteable = false; String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // Can read and write the media mExternalStorageAvailable = mExternalStorageWriteable = true; } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // Can only read the media mExternalStorageAvailable = true; mExternalStorageWriteable = false; } else { // Can't read or write mExternalStorageAvailable = mExternalStorageWriteable = false; } Log.d("DEBUG", "External Media: readable=" + mExternalStorageAvailable + " writable=" + mExternalStorageWriteable); } public String uploadToTwitter() { OAuthData oAuthData = OAuthData.getInstance(); ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setOAuthConsumerKey(oAuthData.getConsumerKey()); cb.setOAuthConsumerSecret(oAuthData.getConsumerSecret()); cb.setOAuthAccessToken(oAuthData.getAccessToken()); cb.setOAuthAccessTokenSecret(oAuthData.getAccessTokenSecret()); TwitterFactory tf = new TwitterFactory(cb.build()); twitter = tf.getInstance(); String[] mindrdrRecord = createMindrdrRecord().split("\\|"); String tweet = mindrdrRecord[1]; String mindrdrRecordId = mindrdrRecord[0]; Log.d("mindrdrRecordId", mindrdrRecord[0]); try { //User user = twitter.verifyCredentials(); StatusUpdate status = new StatusUpdate(tweet); status.setMedia(mPictureFile); twitter4j.Status tStatus = twitter.updateStatus(status); Log.d("Twitter", String.valueOf(tStatus.getId())); updateRecordWithTweetId(mindrdrRecordId, String.valueOf(tStatus.getId())); } catch (TwitterException te) { Log.d("Error", te.getMessage().toString()); mTwitterUpdateId = null; } //we just ignore all errors for the moment and pretend everything is ok to the user return "OK"; } private String updateRecordWithTweetId(String recordId, String tweetId) { HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost( "http://mindrdr-service"); try { List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); nameValuePairs.add(new BasicNameValuePair("recordId", recordId)); nameValuePairs.add(new BasicNameValuePair("tweetId", tweetId)); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpclient.execute(httppost); Log.d("updateRecordWithTweetId", response.toString()); } catch (ClientProtocolException e) { Log.d("updateRecordWithTweetId", e.toString()); return "Fail"; } catch (IOException e) { Log.d("updateRecordWithTweetId", e.toString()); return "Fail"; } return "Success"; } private String createMindrdrRecord() { HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://mindrdr-service"); try { httppost.setEntity(new UrlEncodedFormEntity(mMindSession.toArrayList())); HttpResponse response = httpclient.execute(httppost); String responseBody = EntityUtils.toString(response.getEntity()); Log.d("createMindrdrRecord", responseBody); return responseBody; } catch (ClientProtocolException e) { Log.d("createMindrdrRecordError", e.toString()); return "Fail"; } catch (IOException e) { Log.d("createMindrdrRecordError", e.toString()); return "Fail"; } } } }