Java tutorial
/****************************************************************************** * * Copyright 2014 Paphus Solutions Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.botlibre.sdk.activity; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Random; import org.botlibre.sdk.activity.MainActivity.LaunchType; import org.botlibre.sdk.activity.actions.HttpAction; import org.botlibre.sdk.activity.actions.HttpChatAction; import org.botlibre.sdk.activity.actions.HttpFetchChatAvatarAction; import org.botlibre.sdk.activity.actions.HttpGetImageAction; import org.botlibre.sdk.activity.actions.HttpGetInstancesAction; import org.botlibre.sdk.activity.actions.HttpGetVideoAction; import org.botlibre.sdk.config.AvatarConfig; import org.botlibre.sdk.config.BrowseConfig; import org.botlibre.sdk.config.ChatConfig; import org.botlibre.sdk.config.ChatResponse; import org.botlibre.sdk.config.InstanceConfig; import org.botlibre.sdk.config.VoiceConfig; import org.botlibre.sdk.util.Command; import org.botlibre.sdk.util.TextStream; import org.botlibre.sdk.util.Utils; import org.json.JSONObject; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdView; import org.botlibre.sdk.R; import android.Manifest; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnPreparedListener; import android.net.Uri; import android.os.Bundle; import android.speech.RecognitionListener; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import android.speech.tts.TextToSpeech; import android.support.v4.app.ActivityCompat; import android.util.Log; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.webkit.JavascriptInterface; import android.webkit.WebView; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; import android.widget.VideoView; /** * Activity for chatting with a bot. * To launch this activity from your app you can use the HttpFetchAction passing the bot id or name as a config, and launch=true. */ @SuppressWarnings("deprecation") public class ChatActivity extends LibreActivity implements TextToSpeech.OnInitListener, TextToSpeech.OnUtteranceCompletedListener, RecognitionListener { protected static final int RESULT_SPEECH = 1; protected static final int CAPTURE_IMAGE = 2; protected static final int RESULT_SCAN = 3; protected static final int CAPTURE_VIDEO = 4; protected static boolean DEBUG; private boolean isRecording; public static boolean isListening; public class WebAppInterface { Context context; WebAppInterface(Context context) { this.context = context; } @JavascriptInterface public void postback(final String message) { try { final EditText messageText = (EditText) findViewById(R.id.messageText); messageText.post(new Runnable() { @Override public void run() { try { messageText.setText(message); submitChat(); } catch (Throwable error) { error.printStackTrace(); } } }); } catch (Throwable error) { error.printStackTrace(); } } } protected TextToSpeech tts; protected boolean ttsInit = false; public VideoView videoView; public View videoLayout; public ImageView imageView; protected EditText textView; private boolean volumeChecked = true; private Thread thread; private SpeechRecognizer speech; private LinearLayout menuMLayout; private LinearLayout chatCLayout; private LinearLayout responseLayout; private LinearLayout chatToolBar; private int stateLayouts = 0; private View scrollView; public boolean music = false; private double lastReply = System.currentTimeMillis(); public List<Object> messages = new ArrayList<Object>(); public ChatResponse response; public MediaPlayer audioPlayer; public String currentAudio; public boolean videoError; protected volatile boolean wasSpeaking; protected InstanceConfig instance; private boolean active = true; protected AvatarConfig avatar; protected String avatarId; protected boolean changingVoice; MediaPlayer speechPlayer; protected Random random = new Random(); protected Menu menu; protected Bitmap icon; //flag will check if the mic is ON or OFF public static boolean micLastStat; private boolean failedOfflineLanguage = false; private boolean threadIsOn = false; public void superOnCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); // Remove flag button if a single bot app. if (MainActivity.launchType == LaunchType.Bot) { //findViewById(R.id.flagButton).setVisibility(View.GONE); } //permission required. ActivityCompat.requestPermissions(ChatActivity.this, new String[] { Manifest.permission.RECORD_AUDIO }, 1); //set/Save the current volume from the device. setStreamVolume(); //Music Volume is Enabled. muteMicBeep(false); //For "scream" issue micLastStat = MainActivity.listenInBackground; getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); this.instance = (InstanceConfig) MainActivity.instance; if (this.instance == null) { return; } /*if (MainActivity.showAds) { AdView mAdView = (AdView) findViewById(R.id.adView); AdRequest adRequest = new AdRequest.Builder().build(); mAdView.loadAd(adRequest); } else { AdView mAdView = (AdView) findViewById(R.id.adView); mAdView.setVisibility(View.GONE); }*/ setTitle(this.instance.name); ((TextView) findViewById(R.id.title)).setText(this.instance.name); HttpGetImageAction.fetchImage(this, this.instance.avatar, findViewById(R.id.icon)); ttsInit = false; tts = new TextToSpeech(this, this); if (!MainActivity.handsFreeSpeech) { setMicIcon(false, false); } else if (!MainActivity.listenInBackground) { setMicIcon(false, false); } //Last time will be saved for the MIC. if (MainActivity.listenInBackground && MainActivity.handsFreeSpeech) { microphoneThread(thread); } speech = SpeechRecognizer.createSpeechRecognizer(this); speech.setRecognitionListener(this); //scrollVie added and stuff scrollView = findViewById(R.id.chatList); menuMLayout = (LinearLayout) findViewById(R.id.menuMLayout); chatCLayout = (LinearLayout) findViewById(R.id.chatCLayout); responseLayout = (LinearLayout) findViewById(R.id.responseLayout); chatToolBar = (LinearLayout) findViewById(R.id.chatToolBar); videoView = (VideoView) findViewById(R.id.videoView); resetVideoErrorListener(); videoError = false; imageView = (ImageView) findViewById(R.id.imageView); videoLayout = findViewById(R.id.videoLayout); textView = (EditText) findViewById(R.id.messageText); textView.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { submitChat(); return false; } }); if (MainActivity.translate) { findViewById(R.id.yandex).setVisibility(View.VISIBLE); } else { findViewById(R.id.yandex).setVisibility(View.GONE); } Spinner emoteSpin = (Spinner) findViewById(R.id.emoteSpin); emoteSpin.setAdapter( new EmoteSpinAdapter(this, R.layout.emote_list, Arrays.asList(EmotionalState.values()))); ListView list = (ListView) findViewById(R.id.chatList); list.setAdapter(new ChatListAdapter(this, R.layout.chat_list, this.messages)); list.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); ImageButton button = (ImageButton) findViewById(R.id.speakButton); button.setOnClickListener(new View.OnClickListener() { @TargetApi(23) @Override public void onClick(View v) { if (MainActivity.handsFreeSpeech) { //set the current volume to the setting. setStreamVolume(); //if its ON Or OFF - Switching back and forth MainActivity.listenInBackground = !MainActivity.listenInBackground; //saving the boolean data of MainActivity.listeningInBackground SharedPreferences.Editor cookies = MainActivity.current.getPreferences(Context.MODE_PRIVATE) .edit(); cookies.putBoolean("listenInBackground", MainActivity.listenInBackground); cookies.commit(); if (MainActivity.listenInBackground) { micLastStat = true; try { microphoneThread(thread); } catch (Exception ignore) { } beginListening(); } else { micLastStat = false; microphoneThread(thread); stopListening(); } } else { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, MainActivity.voice.language); try { startActivityForResult(intent, RESULT_SPEECH); textView.setText(""); } catch (ActivityNotFoundException a) { Toast t = Toast.makeText(getApplicationContext(), "Your device doesn't support Speech to Text", Toast.LENGTH_SHORT); t.show(); } } } }); //adding functionality on clicking the image imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (stateLayouts == 4) { stateLayouts = 0; } switch (stateLayouts) { case 0: scrollView.setVisibility(View.VISIBLE); chatCLayout.setVisibility(View.VISIBLE); menuMLayout.setVisibility(View.VISIBLE); responseLayout.setVisibility(View.VISIBLE); chatToolBar.setVisibility(View.VISIBLE); break; case 1: scrollView.setVisibility(View.GONE); break; case 2: responseLayout.setVisibility(View.GONE); chatToolBar.setVisibility(View.GONE); break; case 3: menuMLayout.setVisibility(View.GONE); chatCLayout.setVisibility(View.GONE); break; } stateLayouts++; } }); //adding functionality on clicking the image videoLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (stateLayouts == 4) { stateLayouts = 0; } switch (stateLayouts) { case 0: scrollView.setVisibility(View.VISIBLE); chatCLayout.setVisibility(View.VISIBLE); menuMLayout.setVisibility(View.VISIBLE); responseLayout.setVisibility(View.VISIBLE); chatToolBar.setVisibility(View.VISIBLE); break; case 1: scrollView.setVisibility(View.GONE); break; case 2: responseLayout.setVisibility(View.GONE); chatToolBar.setVisibility(View.GONE); break; case 3: menuMLayout.setVisibility(View.GONE); chatCLayout.setVisibility(View.GONE); break; } stateLayouts++; } }); GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTapEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { boolean isVideo = !MainActivity.disableVideo && !videoError && response != null && response.isVideo(); View imageView = findViewById(R.id.imageView); View videoLayout = findViewById(R.id.videoLayout); if (imageView.getVisibility() == View.VISIBLE) { imageView.setVisibility(View.GONE); } else if (!isVideo) { imageView.setVisibility(View.VISIBLE); } if (videoLayout.getVisibility() == View.VISIBLE) { videoLayout.setVisibility(View.GONE); } else if (isVideo) { videoLayout.setVisibility(View.VISIBLE); } return true; } return false; } }; final GestureDetector detector = new GestureDetector(this, listener); findViewById(R.id.chatList).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return detector.onTouchEvent(event); } }); listener = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTapEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { View avatarLayout = findViewById(R.id.avatarLayout); if (avatarLayout.getVisibility() == View.VISIBLE) { avatarLayout.setVisibility(View.GONE); } else { avatarLayout.setVisibility(View.VISIBLE); } return true; } return false; } }; final GestureDetector detector2 = new GestureDetector(this, listener); /*findViewById(R.id.responseText).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return detector2.onTouchEvent(event); } });*/ WebView responseView = (WebView) findViewById(R.id.responseText); responseView.getSettings().setJavaScriptEnabled(true); responseView.getSettings().setDomStorageEnabled(true); responseView.addJavascriptInterface(new WebAppInterface(this), "Android"); findViewById(R.id.responseImageView).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { View avatarLayout = findViewById(R.id.avatarLayout); if (avatarLayout.getVisibility() == View.VISIBLE) { avatarLayout.setVisibility(View.GONE); } else { avatarLayout.setVisibility(View.VISIBLE); } } }); HttpGetImageAction.fetchImage(this, instance.avatar, this.imageView); HttpGetImageAction.fetchImage(this, instance.avatar, (ImageView) findViewById(R.id.responseImageView)); final ChatConfig config = new ChatConfig(); config.instance = instance.id; config.avatar = this.avatarId; if (MainActivity.translate && MainActivity.voice != null) { config.language = MainActivity.voice.language; } if (MainActivity.disableVideo) { config.avatarFormat = "image"; } else { config.avatarFormat = MainActivity.webm ? "webm" : "mp4"; } config.avatarHD = MainActivity.hd; config.speak = !MainActivity.deviceVoice; // This is required because of a bug in TextToSpeech that prevents onInit being called if an AsynchTask is called... Thread thread1 = new Thread() { public void run() { for (int count = 0; count < 5; count++) { if (ttsInit) { break; } try { Thread.sleep(1000); } catch (Exception exception) { } } HttpAction action = new HttpChatAction(ChatActivity.this, config); action.execute(); } }; thread1.start(); } //thread for the Microphone public Thread microphoneThread(Thread thread) { //make sure its on if it didn't turn off by the user. if 'sleep' is called it will turn the mic off. if (MainActivity.listenInBackground && threadIsOn) { return thread; } //if the user clicked on the Mic while its ON it will turn off and turn the thread off as well. if (threadIsOn) { threadIsOn = false; active = false; try { thread.stop(); } catch (Exception ignore) { } return thread; } //if the user clicked on the Mic while its off it will turn ON the thread. if (!threadIsOn) { threadIsOn = true; active = true; thread = new Thread() { @Override public void run() { Log.e("Thread", "RUNNING"); while (active) { Log.e("Thread", "ACTIVE"); if (!isRecording && isListening && (System.currentTimeMillis() - lastReply) > 5000) { lastReply = System.currentTimeMillis(); debug("speech death restart"); restartListening(); } try { Thread.sleep(1500); } catch (Exception exception) { } } } }; thread.start(); } return thread; } @SuppressLint("Override") public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case 1: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { } else { Toast.makeText(ChatActivity.this, "Permission denied to Record Audio", Toast.LENGTH_SHORT).show(); } return; } } } public void resetChat(View view) { ChatConfig config = new ChatConfig(); config.instance = instance.id; config.avatar = this.avatarId; if (MainActivity.translate && MainActivity.voice != null) { config.language = MainActivity.voice.language; } if (MainActivity.disableVideo) { config.avatarFormat = "image"; } else { config.avatarFormat = MainActivity.webm ? "webm" : "mp4"; } config.avatarHD = MainActivity.hd; config.speak = !MainActivity.deviceVoice; HttpAction action = new HttpChatAction(ChatActivity.this, config); action.execute(); EditText v = (EditText) findViewById(R.id.messageText); v.setText(""); this.messages.clear(); runOnUiThread(new Runnable() { @Override public void run() { ListView list = (ListView) findViewById(R.id.chatList); ((ChatListAdapter) list.getAdapter()).notifyDataSetChanged(); list.invalidateViews(); } }); WebView responseView = (WebView) findViewById(R.id.responseText); responseView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null); } public void resetVideoErrorListener() { videoView.setOnErrorListener(new OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { Log.wtf("Video error", "what:" + what + " extra:" + extra); videoError = true; return true; } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case CAPTURE_IMAGE: { if (resultCode == RESULT_OK) { //TODO Make camera intent stop app from reseting //Uri photoUri = data.getData(); //Do what we like with the photo - send to bot, etc } else if (resultCode == RESULT_CANCELED) { textView.setText("Cancelled"); submitChat(); } break; } case CAPTURE_VIDEO: { if (resultCode == RESULT_OK) { Uri videoUri = data.getData(); //Do what we would like with the video } else if (resultCode == RESULT_CANCELED) { textView.setText("Cancelled"); submitChat(); } break; } case RESULT_SPEECH: { if (resultCode == RESULT_OK && data != null) { ArrayList<String> text = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); textView.setText(text.get(0)); submitChat(); } break; } } IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); if (scanResult != null) { textView.setText("lookup " + scanResult.getContents()); submitChat(); if (scanResult.getContents().startsWith("http")) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(scanResult.getContents())); startActivity(intent); } } } public void flagResponse() { if (MainActivity.user == null) { MainActivity.showMessage("You must sign in to flag a response", this); return; } final EditText text = new EditText(this); MainActivity.prompt("Enter reason for flagging response as offensive", this, text, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { if (instance == null) { return; } ChatConfig config = new ChatConfig(); config.instance = instance.id; config.conversation = MainActivity.conversation; config.speak = !MainActivity.deviceVoice; config.avatar = avatarId; if (MainActivity.translate && MainActivity.voice != null) { config.language = MainActivity.voice.language; } if (MainActivity.disableVideo) { config.avatarFormat = "image"; } else { config.avatarFormat = MainActivity.webm ? "webm" : "mp4"; } config.avatarHD = MainActivity.hd; config.message = text.getText().toString().trim(); if (config.message.equals("")) { return; } messages.add(config); runOnUiThread(new Runnable() { @Override public void run() { ListView list = (ListView) findViewById(R.id.chatList); ((ChatListAdapter) list.getAdapter()).notifyDataSetChanged(); list.invalidateViews(); } }); config.offensive = true; Spinner emoteSpin = (Spinner) findViewById(R.id.emoteSpin); config.emote = emoteSpin.getSelectedItem().toString(); HttpChatAction action = new HttpChatAction(ChatActivity.this, config); action.execute(); EditText v = (EditText) findViewById(R.id.messageText); v.setText(""); emoteSpin.setSelection(0); resetToolbar(); WebView responseView = (WebView) findViewById(R.id.responseText); responseView.loadDataWithBaseURL(null, "thinking...", "text/html", "utf-8", null); } }); } public void submitCorrection() { final EditText text = new EditText(this); MainActivity.prompt("Enter correction to the bot's response (what it should have said)", this, text, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { if (instance == null) { return; } ChatConfig config = new ChatConfig(); config.instance = instance.id; config.conversation = MainActivity.conversation; config.speak = !MainActivity.deviceVoice; config.avatar = avatarId; if (MainActivity.disableVideo) { config.avatarFormat = "image"; } else { config.avatarFormat = MainActivity.webm ? "webm" : "mp4"; } config.avatarHD = MainActivity.hd; config.message = text.getText().toString().trim(); if (config.message.equals("")) { return; } messages.add(config); runOnUiThread(new Runnable() { @Override public void run() { ListView list = (ListView) findViewById(R.id.chatList); ((ChatListAdapter) list.getAdapter()).notifyDataSetChanged(); list.invalidateViews(); } }); config.correction = true; Spinner emoteSpin = (Spinner) findViewById(R.id.emoteSpin); config.emote = emoteSpin.getSelectedItem().toString(); HttpChatAction action = new HttpChatAction(ChatActivity.this, config); action.execute(); EditText v = (EditText) findViewById(R.id.messageText); v.setText(""); emoteSpin.setSelection(0); resetToolbar(); WebView responseView = (WebView) findViewById(R.id.responseText); responseView.loadDataWithBaseURL(null, "thinking...", "text/html", "utf-8", null); } }); } public void submitChat() { ChatConfig config = new ChatConfig(); config.instance = this.instance.id; config.conversation = MainActivity.conversation; config.speak = !MainActivity.deviceVoice; config.avatar = this.avatarId; if (MainActivity.translate && MainActivity.voice != null) { config.language = MainActivity.voice.language; } if (MainActivity.disableVideo) { config.avatarFormat = "image"; } else { config.avatarFormat = MainActivity.webm ? "webm" : "mp4"; } config.avatarHD = MainActivity.hd; EditText v = (EditText) findViewById(R.id.messageText); config.message = v.getText().toString().trim(); if (config.message.equals("")) { return; } this.messages.add(config); runOnUiThread(new Runnable() { @Override public void run() { ListView list = (ListView) findViewById(R.id.chatList); ((ChatListAdapter) list.getAdapter()).notifyDataSetChanged(); list.invalidateViews(); } }); Spinner emoteSpin = (Spinner) findViewById(R.id.emoteSpin); config.emote = emoteSpin.getSelectedItem().toString(); HttpChatAction action = new HttpChatAction(ChatActivity.this, config); action.execute(); v.setText(""); emoteSpin.setSelection(0); resetToolbar(); WebView responseView = (WebView) findViewById(R.id.responseText); responseView.loadDataWithBaseURL(null, "thinking...", "text/html", "utf-8", null); //Check the volume AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); int volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); if (volume <= 3 && volumeChecked) { Toast.makeText(this, "Please check 'Media' volume", Toast.LENGTH_LONG).show(); volumeChecked = false; } //stop letting the mic on. stopListening(); //its Important for "sleep" "scream" ...etc commands. //this will turn off the mic MainActivity.listenInBackground = false; } public void toggleSound(View view) { toggleSound(); } public void toggleSound() { MainActivity.sound = !MainActivity.sound; resetToolbar(); } public void toggleHandsFreeSpeech() { MainActivity.handsFreeSpeech = !MainActivity.handsFreeSpeech; if (!MainActivity.handsFreeSpeech) { stopListening(); } else if (MainActivity.handsFreeSpeech) { beginListening(); } SharedPreferences.Editor cookies = MainActivity.current.getPreferences(Context.MODE_PRIVATE).edit(); cookies.putBoolean("handsfreespeech", MainActivity.handsFreeSpeech); cookies.commit(); } public void toggleDisableVideo() { if (this.videoError) { this.videoError = false; MainActivity.disableVideo = false; } else { MainActivity.disableVideo = !MainActivity.disableVideo; } } public void changeAvatar() { MainActivity.browsing = true; BrowseConfig config = new BrowseConfig(); config.type = "Avatar"; config.typeFilter = "Featured"; config.contentRating = MainActivity.contentRating; HttpGetInstancesAction action = new HttpGetInstancesAction(this, config); action.execute(); } public void changeVoice() { this.changingVoice = true; Intent intent = new Intent(this, ChangeVoiceActivity.class); startActivity(intent); } public void toggleDeviceVoice() { MainActivity.deviceVoice = !MainActivity.deviceVoice; } public void toggleFlag(View view) { flagResponse(); } public void toggleCorrection(View view) { submitCorrection(); } public void menu(View view) { openOptionsMenu(); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.menu_chat, menu); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { this.menu = menu; resetMenu(); return true; } public void resetMenu() { if (this.menu == null) { return; } this.menu.findItem(R.id.menuSound).setChecked(MainActivity.sound); this.menu.findItem(R.id.menuDeviceVoice).setChecked(MainActivity.deviceVoice); this.menu.findItem(R.id.menuHandsFreeSpeech).setChecked(MainActivity.handsFreeSpeech); this.menu.findItem(R.id.menuDisableVideo).setChecked(MainActivity.disableVideo || this.videoError); this.menu.findItem(R.id.menuHD).setChecked(MainActivity.hd); this.menu.findItem(R.id.menuWebm).setChecked(MainActivity.webm); } public void changeLanguage(View view) { MainActivity.changeLanguage(this, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { resetTTS(); if (MainActivity.translate) { findViewById(R.id.yandex).setVisibility(View.VISIBLE); } else { findViewById(R.id.yandex).setVisibility(View.GONE); } } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menuChangeLanguage: changeLanguage(null); return true; // case R.id.menuChangeVoice: // changeVoice(); // return true; case R.id.menuHandsFreeSpeech: toggleHandsFreeSpeech(); return true; case R.id.menuSound: toggleSound(); return true; case R.id.menuDeviceVoice: toggleDeviceVoice(); return true; case R.id.menuDisableVideo: toggleDisableVideo(); return true; case R.id.menuCorrection: submitCorrection(); return true; case R.id.menuFlag: flagResponse(); return true; case R.id.menuHD: MainActivity.hd = !MainActivity.hd; return true; case R.id.menuWebm: MainActivity.webm = !MainActivity.webm; return true; case R.id.menuChangeAvatar: changeAvatar(); return true; case R.id.MicConfig: MicConfiguration(); finish(); return true; default: return super.onOptionsItemSelected(item); } } /** * Disconnect from the conversation. */ public void disconnect(View view) { finish(); } public void resetToolbar() { if (MainActivity.sound) { findViewById(R.id.soundButton).setBackgroundResource(R.drawable.sound); } else { findViewById(R.id.soundButton).setBackgroundResource(R.drawable.mute); } } /** * Clear the log. */ public void clear(View view) { WebView log = (WebView) findViewById(R.id.logText); log.loadDataWithBaseURL(null, "", "text/html", "utf-8", null); } @Override public void onResume() { MainActivity.searching = false; MainActivity.searchingPosts = false; if (MainActivity.browsing && (MainActivity.instance instanceof AvatarConfig)) { if (MainActivity.user == null || MainActivity.user.type == null || MainActivity.user.type.isEmpty() || MainActivity.user.type.equals("Basic")) { //MainActivity.showMessage("You must upgrade to get access to this avatar", this); //super.onResume(); //return; } this.avatar = (AvatarConfig) MainActivity.instance; this.avatarId = this.avatar.id; if (this.imageView.getVisibility() == View.GONE) { this.imageView.setVisibility(View.VISIBLE); } if (this.videoLayout.getVisibility() == View.VISIBLE) { this.videoLayout.setVisibility(View.GONE); } HttpGetImageAction.fetchImage(this, this.avatar.avatar, this.imageView); AvatarConfig avatarConfig = (AvatarConfig) this.avatar.credentials(); HttpFetchChatAvatarAction action = new HttpFetchChatAvatarAction(this, avatarConfig); action.execute(); } MainActivity.browsing = false; if ((MainActivity.instance instanceof InstanceConfig) && MainActivity.instance.id.equals(this.instance.id)) { this.instance = (InstanceConfig) MainActivity.instance; } else { MainActivity.instance = this.instance; } if (this.changingVoice) { this.changingVoice = false; resetTTS(); } super.onResume(); } public void resetTTS() { try { this.tts.stop(); } catch (Exception exception) { } try { this.tts.shutdown(); } catch (Exception exception) { } this.tts = new TextToSpeech(this, this); } public String getAvatarIcon(ChatResponse config) { if (this.avatar != null) { return this.avatar.avatar; } if (config == null || config.isVideo()) { return this.instance.avatar; } return config.avatar; } public void resetAvatar(AvatarConfig config) { HttpGetImageAction.fetchImage(this, config.avatar, this.imageView); HttpGetImageAction.fetchImage(this, config.avatar, findViewById(R.id.responseImageView)); } public void MicConfiguration() { Intent i = new Intent(this, MicConfiguration.class); startActivity(i); finish(); } @Override public void onDestroy() { try { active = false; stopListening(); try { thread = null; } catch (Exception ex) { Log.e("micError", ex.toString()); } if (this.instance != null) { ChatConfig config = new ChatConfig(); config.instance = this.instance.id; config.conversation = MainActivity.conversation; config.disconnect = true; HttpChatAction action = new HttpChatAction(this, config); action.execute(); } muteMicBeep(false); if (this.tts != null) { try { this.tts.stop(); } catch (Exception ignore) { } try { this.tts.shutdown(); } catch (Exception ignore) { } } if (this.audioPlayer != null) { try { this.audioPlayer.stop(); } catch (Exception ignore) { } try { this.audioPlayer.release(); } catch (Exception ignore) { } } if (this.speechPlayer != null) { try { this.speechPlayer.stop(); } catch (Exception ignore) { } try { this.speechPlayer.release(); } catch (Exception ignore) { } } } catch (Exception ex) { Log.e("micError", ex.toString()); } super.onDestroy(); } @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { Locale locale = null; VoiceConfig voice = MainActivity.voice; if (voice != null && voice.language != null && voice.language.length() > 0) { locale = new Locale(voice.language); } else { locale = Locale.US; } int result = this.tts.setLanguage(locale); float pitch = 1; if (voice != null && voice.pitch != null && voice.pitch.length() > 0) { try { pitch = Float.valueOf(voice.pitch); } catch (Exception exception) { } } float speechRate = 1; if (voice != null && voice.speechRate != null && voice.speechRate.length() > 0) { try { speechRate = Float.valueOf(voice.speechRate); } catch (Exception exception) { } } this.tts.setPitch(pitch); this.tts.setSpeechRate(speechRate); if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { Log.e("TTS", "This Language is not supported"); } this.tts.setOnUtteranceCompletedListener(this); } else { Log.e("TTS", "Initilization Failed!"); } } /** * Add JavaScript to the HTML to raise postback events to send messages to the bot. */ public String linkPostbacks(String html) { if (html.contains("button")) { TextStream stream = new TextStream(html); StringWriter writer = new StringWriter(); while (!stream.atEnd()) { writer.write(stream.upToAll("<button", true)); if (!stream.atEnd()) { String element = stream.upTo('>', true); String button = stream.upTo('<', false); writer.write(" onclick=\"Android.postback('" + button + "')\" "); writer.write(element); writer.write(button); } } html = writer.toString(); } if (html.contains("chat:")) { TextStream stream = new TextStream(html); StringWriter writer = new StringWriter(); while (!stream.atEnd()) { writer.write(stream.upToAll("href=\"", true)); if (stream.atEnd()) { break; } String protocol = stream.upTo(':', true); if (!protocol.equals("chat:")) { writer.write(protocol); continue; } String chat = stream.upTo('"', false); writer.write("#\""); writer.write(" onclick=\"Android.postback('" + chat + "')\" "); } html = writer.toString(); } if (html.contains("select")) { TextStream stream = new TextStream(html); StringWriter writer = new StringWriter(); while (!stream.atEnd()) { writer.write(stream.upToAll("<select", true)); if (!stream.atEnd()) { writer.write(" onchange=\"Android.postback(this.value)\" "); } } html = writer.toString(); } return html; } public void response(final ChatResponse response) { if (speechPlayer != null || tts != null) { try { tts.stop(); speechPlayer.pause(); } catch (Exception ignore) { Log.e("RESPONSE", "Error: " + ignore.getMessage()); } } //needs when calling "sleep" or the its not going to let the mic off //also to stop the mic until the bot finish the sentence try { stopListening(); this.response = response; String status = ""; if (response.emote != null && !response.emote.equals("NONE")) { status = status + response.emote.toLowerCase(); } if (response.action != null) { if (!status.isEmpty()) { status = status + " "; } status = status + response.action; } if (response.pose != null) { if (!status.isEmpty()) { status = status + " "; } status = status + response.pose; } if (response.command != null) { JSONObject jsonObject = response.getCommand(); Command command = new Command(this, jsonObject); } TextView statusView = (TextView) findViewById(R.id.statusText); statusView.setText(status); final String text = response.message; final ListView list = (ListView) findViewById(R.id.chatList); if (text == null) { list.post(new Runnable() { @Override public void run() { ChatResponse ready = new ChatResponse(); ready.message = "ready"; messages.add(ready); ((ChatListAdapter) list.getAdapter()).notifyDataSetChanged(); list.invalidateViews(); if (list.getCount() > 2) { list.setSelection(list.getCount() - 2); } beginListening(); } }); return; } list.post(new Runnable() { @Override public void run() { messages.add(response); ((ChatListAdapter) list.getAdapter()).notifyDataSetChanged(); list.invalidateViews(); if (list.getCount() > 2) { list.setSelection(list.getCount() - 2); } } }); WebView responseView = (WebView) findViewById(R.id.responseText); String html = Utils.linkHTML(text); if (html.contains("<") && html.contains(">")) { html = linkPostbacks(html); } responseView.loadDataWithBaseURL(null, html, "text/html", "utf-8", null); boolean talk = (text.trim().length() > 0) && (MainActivity.deviceVoice || (this.response.speech != null && this.response.speech.length() > 0)); if (MainActivity.sound && talk) { if (!MainActivity.disableVideo && !videoError && this.response.isVideo() && this.response.isVideoTalk()) { videoView.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { try { mp.setLooping(true); if (!MainActivity.deviceVoice) { // Voice audio speechPlayer = playAudio(response.speech, false, false, false); speechPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mp.release(); videoView.post(new Runnable() { public void run() { cycleVideo(response); } }); runOnUiThread(new Runnable() { public void run() { if (!music) { beginListening(); } } }); } }); speechPlayer.start(); } else { HashMap<String, String> params = new HashMap<String, String>(); params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "id"); tts.speak(Utils.stripTags(text), TextToSpeech.QUEUE_FLUSH, params); } } catch (Exception exception) { Log.wtf(exception.getMessage(), exception); } } }); playVideo(this.response.avatarTalk, false); } else if (talk) { if (!MainActivity.deviceVoice) { // Voice audio playAudio(this.response.speech, false, false, true); } else { HashMap<String, String> params = new HashMap<String, String>(); params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "id"); this.tts.speak(Utils.stripTags(text), TextToSpeech.QUEUE_FLUSH, params); } } } else if (talk && (!MainActivity.disableVideo && !videoError && this.response.isVideo() && this.response.avatarTalk != null)) { videoView.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.setLooping(false); } }); videoView.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { videoView.setOnCompletionListener(null); cycleVideo(response); } }); playVideo(this.response.avatarTalk, false); runOnUiThread(new Runnable() { public void run() { beginListening(); } }); } else { runOnUiThread(new Runnable() { public void run() { beginListening(); } }); } } catch (Exception exception) { Log.wtf(exception.getMessage(), exception); } if (micLastStat) { MainActivity.listenInBackground = true; } } @Override public void onPause() { stopListening(); muteMicBeep(false); super.onPause(); } public void playVideo(String video, boolean loop) { if (loop) { videoView.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.setLooping(true); } }); } try { Uri videoUri = HttpGetVideoAction.fetchVideo(this, video); if (videoUri == null) { videoUri = Uri.parse(MainActivity.connection.fetchImage(video).toURI().toString()); } videoView.setVideoURI(videoUri); videoView.start(); } catch (Exception exception) { Log.wtf(exception.toString(), exception); } } public void cycleVideo(final ChatResponse response) { if ((response.avatar2 == null || response.avatar3 == null || response.avatar4 == null || response.avatar5 == null) || (response.avatar2.isEmpty() || response.avatar3.isEmpty() || response.avatar4.isEmpty() || response.avatar5.isEmpty()) || (response.avatar.equals(response.avatar2) && response.avatar2.equals(response.avatar3) && response.avatar3.equals(response.avatar4) && response.avatar4.equals(response.avatar5))) { playVideo(response.avatar, true); return; } videoView.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.setLooping(false); } }); videoView.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { cycleVideo(response); } }); int value = random.nextInt(5); String avatar = response.avatar; switch (value) { case 1: avatar = response.avatar2; break; case 2: avatar = response.avatar3; break; case 3: avatar = response.avatar5; break; case 14: avatar = response.avatar4; break; } try { Uri videoUri = HttpGetVideoAction.fetchVideo(this, avatar); if (videoUri == null) { videoUri = Uri.parse(MainActivity.connection.fetchImage(avatar).toURI().toString()); } videoView.setVideoURI(videoUri); videoView.start(); } catch (Exception exception) { Log.wtf(exception.toString(), exception); } } public MediaPlayer playAudio(String audio, boolean loop, boolean cache, boolean start) { try { Uri audioUri = null; if (cache) { audioUri = HttpGetVideoAction.fetchVideo(this, audio); } if (audioUri == null) { audioUri = Uri.parse(MainActivity.connection.fetchImage(audio).toURI().toString()); } final MediaPlayer audioPlayer = new MediaPlayer(); audioPlayer.setDataSource(getApplicationContext(), audioUri); audioPlayer.setOnErrorListener(new OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { Log.wtf("Audio error", "what:" + what + " extra:" + extra); audioPlayer.stop(); audioPlayer.release(); return true; } }); audioPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { audioPlayer.release(); runOnUiThread(new Runnable() { public void run() { try { beginListening(); } catch (Exception e) { Log.e("ChatActivity", "MediaPlayer: " + e.getMessage()); } } }); } }); audioPlayer.prepare(); audioPlayer.setLooping(loop); if (start) { audioPlayer.start(); } return audioPlayer; } catch (Exception exception) { Log.wtf(exception.toString(), exception); return null; } } @Override public void onUtteranceCompleted(String utteranceId) { debug("onUtteranceCompleted"); runOnUiThread(new Runnable() { public void run() { try { beginListening(); } catch (Exception ignore) { } } }); try { if (!MainActivity.disableVideo && !videoError && this.response.isVideo()) { this.videoView.post(new Runnable() { public void run() { cycleVideo(response); } }); } } catch (Exception exception) { Log.wtf(exception.toString(), exception); } } public TextToSpeech getTts() { return tts; } public void setTts(TextToSpeech tts) { this.tts = tts; } public VideoView getVideoView() { return videoView; } public void setVideoView(VideoView videoView) { this.videoView = videoView; } public List<Object> getMessages() { return messages; } public void setMessages(List<Object> messages) { this.messages = messages; } public ChatResponse getResponse() { return response; } public void setResponse(ChatResponse response) { this.response = response; } public MediaPlayer getAudioPlayer() { return audioPlayer; } public void setAudioPlayer(MediaPlayer audioPlayer) { this.audioPlayer = audioPlayer; } public String getCurrentAudio() { return currentAudio; } public void setCurrentAudio(String currentAudio) { this.currentAudio = currentAudio; } public boolean getWasSpeaking() { return wasSpeaking; } public void setWasSpeaking(boolean wasSpeaking) { this.wasSpeaking = wasSpeaking; } private void stopListening() { debug("stopListening"); try { muteMicBeep(false); isListening = false; this.speech.stopListening(); setMicIcon(false, false); } catch (Exception ignore) { Log.e("StopListening", "Error" + ignore.getMessage()); } } private void restartListening() { lastReply = System.currentTimeMillis(); debug("restartListening"); if (!MainActivity.listenInBackground) { return; } if (!isListening) { return; } this.runOnUiThread(new Runnable() { public void run() { try { Log.e("ChatActivity", "Start Listening from Restart"); beginListening(); } catch (Exception e) { Log.e("ErrorChatActivity", "Error: " + e.getMessage()); } } }); } public void scanBarcode(View v) { IntentIntegrator integrator = new IntentIntegrator(this); integrator.initiateScan(); } private void setMicIcon(boolean on, boolean recording) { try { View micButton = findViewById(R.id.speakButton); if (!on) { ((ImageButton) micButton).setImageResource(R.drawable.micoff); } else if (on && recording) { ((ImageButton) micButton).setImageResource(R.drawable.micrecording); } else { ((ImageButton) micButton).setImageResource(R.drawable.mic); } } catch (Exception e) { Log.e("ChatActivity.setMicIcon", "" + e.getMessage()); } } @Override public void onBeginningOfSpeech() { debug("onBeginningOfSpeech"); Log.e("onBeginningOfSpeech", ""); setMicIcon(true, true); isRecording = true; } @Override public void onBufferReceived(byte[] arg0) { Log.e("onBufferReceived", ""); } @Override public void onEndOfSpeech() { debug("onEndOfSpeech:"); isRecording = false; lastReply = System.currentTimeMillis(); Log.e("onEndOfSpeech", ""); setMicIcon(false, false); } public void debug(final String text) { if (!DEBUG) { return; } final ListView list = (ListView) findViewById(R.id.chatList); list.post(new Runnable() { @Override public void run() { ChatResponse ready = new ChatResponse(); ready.message = text; messages.add(ready); ((ChatListAdapter) list.getAdapter()).notifyDataSetChanged(); list.invalidateViews(); if (list.getCount() > 2) { list.setSelection(list.getCount() - 2); } } }); return; } @Override public void onError(int error) { debug("onError:" + error); Log.d("onError Info", "ChatActivity on error executes here!"); try { isRecording = false; lastReply = System.currentTimeMillis(); this.speech.destroy(); this.speech = SpeechRecognizer.createSpeechRecognizer(this); this.speech.setRecognitionListener(this); setMicIcon(false, false); muteMicBeep(false); setStreamVolume(); if (error == SpeechRecognizer.ERROR_AUDIO) { Log.d("System.out", "Error: Audio Recording Error"); } else if (error == SpeechRecognizer.ERROR_CLIENT) { Log.d("System.out", "Error: Other client side error"); restartListening(); } else if (error == SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS) { Log.d("System.out", "Error: INsufficient permissions"); } else if (error == SpeechRecognizer.ERROR_NETWORK) { Log.d("System.out", "Error: Other network Error"); } else if (error == SpeechRecognizer.ERROR_NETWORK_TIMEOUT) { Log.d("System.out", "Error: Network operation timed out"); } else if (error == SpeechRecognizer.ERROR_NO_MATCH) { Log.d("System.out", "Error: No recognition result matched"); restartListening(); } else if (error == SpeechRecognizer.ERROR_RECOGNIZER_BUSY) { Log.d("System.out", "Error: Recognition service busy"); restartListening(); } else if (error == SpeechRecognizer.ERROR_SERVER) { Log.d("System.out", "Error: Server Error"); failedOfflineLanguage = true; restartListening(); } else if (error == SpeechRecognizer.ERROR_SPEECH_TIMEOUT) { Log.d("System.out", "Error: NO speech input"); isListening = true; restartListening(); } } catch (Exception e) { Log.e("micError", e.getMessage()); } } @Override public void onEvent(int arg0, Bundle arg1) { Log.e("OnEvent", "Listening OnEvent"); debug("onEvent:" + arg0); } @Override public void onPartialResults(Bundle arg0) { debug("onPartialResults:"); } @Override public void onReadyForSpeech(Bundle arg0) { debug("onReadyForSpeech:"); Log.e("onReadyForSpeech", ""); setMicIcon(true, false); } @Override public void onResults(Bundle results) { debug("onResults:"); muteMicBeep(false); List<String> text = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); this.textView.setText(text.get(0)); submitChat(); } @Override public void onRmsChanged(float arg0) { } private void muteMicBeep(boolean mute) { debug("muteMicBeep:" + mute + ":" + MainActivity.volume); AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); if (mute) { //if its true then the Volume will be zero. audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0); } else { //if its false, the Volume will put back on audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, MainActivity.volume, 0); } } private void setStreamVolume() { AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); int volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); if (volume != 0) { debug("setStreamVolume:" + volume); Log.d("ChatActivity", "The volume changed and saved to : " + volume); MainActivity.volume = volume; } } @TargetApi(23) private void beginListening() { lastReply = System.currentTimeMillis(); setStreamVolume(); debug("beginListening:"); try { if (!MainActivity.handsFreeSpeech) { return; } if (MainActivity.handsFreeSpeech) { muteMicBeep(true); isListening = true; } if (!MainActivity.listenInBackground) { muteMicBeep(false); return; } } catch (Exception ignore) { Log.e("Error", "BeginListening"); } Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); if (MainActivity.offlineSpeech) { intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, MainActivity.voice.language); if (!this.failedOfflineLanguage) { intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US"); // intent.putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, true); } intent.putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, true); } else { if (MainActivity.voice.language != null && !MainActivity.voice.language.isEmpty()) { intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, MainActivity.voice.language); if (!this.failedOfflineLanguage) { intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, MainActivity.voice.language); } } else { intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en"); if (!this.failedOfflineLanguage) { intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en"); } } } try { Log.d("BeginListening", "StartListening"); this.speech.startListening(intent); setMicIcon(true, false); } catch (ActivityNotFoundException a) { Log.d("BeginListening", "CatchError: " + a.getMessage()); Toast t = Toast.makeText(getApplicationContext(), "Your device doesn't support Speech to Text", Toast.LENGTH_SHORT); t.show(); } } /*private static Uri getOutputMediaFileUri(int type) { return Uri.fromFile(saveImageVideo(type)); } private static File saveImageVideo(int type) { File directory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "BotLibre"); //Create a storage directory if it does not exist if (! directory.exists()) { if (! directory.mkdirs()) { Log.d("BotLibre", "failed to create directory"); return null; } } //Create a media file name File savedFile; String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); if (type == MEDIA_TYPE_IMAGE) { savedFile = new File(directory.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); } //else if video add code here else { return null; } return savedFile; }*/ }