/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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.openintents.plaphoons.ui; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Color; import android.media.AudioManager; import android.media.SoundPool; import android.media.SoundPool.OnLoadCompleteListener; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceManager; import android.print.PrintAttributes; import android.print.PrintDocumentAdapter; import android.print.PrintJob; import android.print.PrintManager; import android.speech.tts.TextToSpeech; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.MarginLayoutParams; import android.view.Window; import android.view.WindowManager; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.EditText; import android.widget.Toast; import org.openintents.plaphoons.Log; import org.openintents.plaphoons.PlaFileParser; import org.openintents.plaphoons.PlaphoonsApplication; import org.openintents.plaphoons.SampleTalkCollection; import org.openintents.plaphoons.SampleTalkCollectionPhone; import org.openintents.plaphoons.domain.TalkInfo; import org.openintents.plaphoons.domain.TalkInfoCollection; import org.openintents.plaphoons.sample.R; import org.openintents.plaphoons.ui.widget.FlowLayout; import org.openintents.plaphoons.ui.widget.SquareGridLayout; import org.openintents.plaphoons.ui.widget.TalkButton; import org.openintents.plaphoons.ui.widget.TalkButton.ClickHandler; import org.openintents.plaphoons.uitl.Helper; import java.io.IOException; import java.util.AbstractCollection; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class MainActivity extends Activity implements OnLoadCompleteListener, ClickHandler { private static final int NOTIFICATION_DEFAULT = 1; private static final String ACTION_DIALOG = "org.openintents.plaphoons.action.DIALOG"; private static final int REQUEST_CODE_DATA_CHECK = 1000; private static final int REQUEST_CODE_PREFERENCES = 2000; protected String mEncoding; protected boolean mHasDigitizer; private View mActionBarView; private String[] mToggleLabels = {"Show Titles", "Hide Titles"}; private int mLabelIndex = 1; private TalkInfoCollection mPanel; private PlaFileParser mParser; private String mPlaRootDir; private String mPlaFilename; private String mCurrentPlaFilename; private boolean mUseSample; private ArrayList<String> mParentStack = new ArrayList<>(); private SoundPool mSoundPool; private int mPendingSound; private EditText mText; private int mQueueMode; private List<TalkInfo> mTextStack = new ArrayList<>(); private boolean mPlayControlOnly; private FlowLayout mTextAsImages; private boolean mShowTextAsImages; private WebView mWebView; private AbstractCollection<PrintJob> mPrintJobs = new ArrayList<>(); private boolean mPrintText; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); if (Build.VERSION.SDK_INT >= 11) { HoneycombHelper.fullScreen(this); } mHasDigitizer = getPackageManager().hasSystemFeature( "android.hardware.touchscreen.pen"); mText = (EditText) findViewById(R.id.text); mTextAsImages = (FlowLayout) findViewById(R.id.text_as_images); mParser = new PlaFileParser(); setValuesFromSavedInstanceState(savedInstanceState); mSoundPool = new SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0); mSoundPool.setOnLoadCompleteListener(this); } private void setValuesFromSavedInstanceState(Bundle savedInstanceState) { // If talk panel is not saved to the savedInstanceState, // 0 is returned by default. if (savedInstanceState != null) { mCurrentPlaFilename = savedInstanceState .getString("currentPlaFile"); mParentStack = savedInstanceState.getStringArrayList("parentStack"); } } private void setValuesFromPreferences() { SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(this); // read .pla file mPlaRootDir = prefs.getString("pladir", Environment .getExternalStorageDirectory().getAbsolutePath()); mPlaFilename = prefs.getString("plafile", null); mUseSample = prefs.getBoolean("usesample", false); mEncoding = prefs.getString("encoding", "iso-8859-1"); mQueueMode = (prefs.getBoolean("queuemodedrop", true) ? TextToSpeech.QUEUE_FLUSH : TextToSpeech.QUEUE_ADD); mPlayControlOnly = prefs.getBoolean("playcontrolonly", false); mShowTextAsImages = prefs.getBoolean("showtextasimages", false); mPrintText = prefs.getBoolean("printtext", false); } public void showPanel(final TalkInfoCollection tiCollection, TalkInfoCollection parent) { Log.v("show " + tiCollection); if (tiCollection.showTextBox) { mText.setVisibility(mShowTextAsImages ? View.GONE : View.VISIBLE); mTextAsImages.setVisibility(mShowTextAsImages ? View.VISIBLE : View.GONE); } else { mText.setVisibility(View.GONE); mText.setVisibility(View.GONE); } /* Find viewGroup defined in main.xml */ SquareGridLayout viewGroup = (SquareGridLayout) findViewById(R.id.talker_layout); viewGroup.setSize(tiCollection.rows + (tiCollection.showTextBox ? 1 : 0), tiCollection.columns); viewGroup.removeAllViews(); LayoutInflater li = getLayoutInflater(); for (int i = 0; i < tiCollection.rows; i++) { for (int j = 0; j < tiCollection.columns; j++) { TalkButton tb = (TalkButton) li.inflate(R.layout.talkbutton, null); TalkInfo ti; if (i >= tiCollection.infos.length || j >= tiCollection.infos[i].length) { ti = new TalkInfo(); } else { ti = tiCollection.infos[i][j]; } tb.setTalkInfo(ti); tb.updateData(mPlaRootDir); tb.setClickHandler(mHasDigitizer, tiCollection, this); MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); lp.setMargins(0, 0, 0, 0); /* Add Button to row. */ viewGroup.addView(tb, lp); } } if (tiCollection.showTextBox) { if (tiCollection.columns > 2) { TalkButton tb = (TalkButton) li.inflate(R.layout.talkbutton, null); tb.setTalkInfo(new TalkInfo(getString(R.string.home), Color.WHITE, R.drawable.home)); tb.updateData(null); tb.setClickHandler(mHasDigitizer, tiCollection, new TalkButton.ClickHandler() { @Override public void onButtonClick( TalkInfoCollection tiCollection, TalkButton b) { home(); } }); tb.setBackgroundResource(R.drawable.picture_frame_control); MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); lp.setMargins(0, 0, 0, 0); /* Add Button to row. */ viewGroup.addView(tb, lp); } TalkButton tb = (TalkButton) li.inflate(R.layout.talkbutton, null); tb.setTalkInfo(new TalkInfo(getString(R.string.play), Color.WHITE, R.drawable.play)); tb.updateData(null); tb.setClickHandler(mHasDigitizer, tiCollection, new TalkButton.ClickHandler() { @Override public void onButtonClick( TalkInfoCollection tiCollection, TalkButton b) { playText(); } }); tb.setBackgroundResource(R.drawable.picture_frame_control); MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); lp.setMargins(0, 0, 0, 0); /* Add Button to row. */ viewGroup.addView(tb, lp); tb = (TalkButton) li.inflate(R.layout.talkbutton, null); tb.setTalkInfo(new TalkInfo(getString(R.string.delete), Color.WHITE, R.drawable.delete)); tb.updateData(null); tb.setClickHandler(mHasDigitizer, tiCollection, new TalkButton.ClickHandler() { @Override public void onButtonClick( TalkInfoCollection tiCollection, TalkButton b) { deleteText(); } }); tb.setBackgroundResource(R.drawable.picture_frame_control); lp = new ViewGroup.MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); lp.setMargins(0, 0, 0, 0); /* Add Button to row. */ viewGroup.addView(tb, lp); } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.preferences: Intent intent = new Intent(this, PreferencesActivity.class); startActivityForResult(intent, REQUEST_CODE_PREFERENCES); return true; case R.id.about: try { AboutDialogBuilder.create(this).show(); } catch (NameNotFoundException e) { e.printStackTrace(); } return true; case R.id.launcher: try { Intent target = new Intent(); target.setAction(Intent.ACTION_MAIN); target.addCategory(Intent.CATEGORY_HOME); Intent chooser = Intent.createChooser(target, getString(R.string.choose_launcher)); startActivity(chooser); } catch (ActivityNotFoundException e) { e.printStackTrace(); } return true; default: return super.onOptionsItemSelected(item); } } @Override protected void onResume() { super.onResume(); setValuesFromPreferences(); // TODO decide whether to show or open the panel openPanel(); } private void openPanel() { Log.v("openPanel"); new AsyncTask<TalkInfoCollection, Void, TalkInfoCollection>() { @Override protected TalkInfoCollection doInBackground( TalkInfoCollection... params) { if (TextUtils.isEmpty(mCurrentPlaFilename)) { mCurrentPlaFilename = mPlaFilename; } TalkInfoCollection panel = null; if (mUseSample || TextUtils.isEmpty(mCurrentPlaFilename)) { if (Helper.isTablet(getResources().getConfiguration())) { panel = SampleTalkCollection.acceuil; } else { panel = SampleTalkCollectionPhone.acceuil; } } else { String fullFilePath = mPlaRootDir + "/" + mCurrentPlaFilename; Log.v("open " + fullFilePath); try { panel = mParser.parseFile(fullFilePath, mEncoding); } catch (IOException e) { e.printStackTrace(); } if (panel != null) { for (TalkInfo[] tis : panel.infos) { for (TalkInfo ti : tis) { if (ti.isTextWav()) { String wavFilePath = mPlaRootDir + "/" + ti.text; Log.v("open " + wavFilePath); ti.soundId = mSoundPool .load(wavFilePath, 1); } } } } } panel.showTextBox = true; return panel; } protected void onPostExecute(TalkInfoCollection result) { if (result == null) { Toast.makeText(MainActivity.this, R.string.parsing_pla_file_failed, Toast.LENGTH_LONG) .show(); } else { mPanel = result; showPanel(mPanel, null); } } }.execute(); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_DATA_CHECK) { if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { // success } else { // missing data, install it Intent installIntent = new Intent(); installIntent .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(installIntent); } } else if (requestCode == REQUEST_CODE_PREFERENCES) { mCurrentPlaFilename = null; } } @Override public boolean onPrepareOptionsMenu(Menu menu) { return true; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("currentPlaFile", mCurrentPlaFilename); outState.putStringArrayList("parentStack", mParentStack); } @Override public void onLoadComplete(SoundPool sp, int id, int status) { Log.v("open " + id + " " + status); if (mPendingSound == id) { sp.play(id, 1, 1, 0, 0, 1); } } @Override public void onButtonClick(TalkInfoCollection tiCollection, TalkButton tb) { TalkInfo talkInfo = tb.mTalkInfo; if (talkInfo.text != null) { if (talkInfo.child == null || talkInfo.childFilename == null || talkInfo.childFilename.length() == 0) { mText.getText().append(talkInfo.text + " "); mTextStack.add(talkInfo); TalkButton talkButton = (TalkButton) getLayoutInflater().inflate(R.layout.talkbutton, null); talkButton.setTalkInfo(talkInfo); talkButton.updateData(mPlaRootDir); mTextAsImages.addView(talkButton); } if (!mPlayControlOnly) { if (talkInfo.isTextWav()) { final String fullFilePath = mPlaRootDir + "/" + talkInfo.text; Log.v("open " + fullFilePath); if (talkInfo.soundId > 0) { int soundId = mSoundPool.play(talkInfo.soundId, 1, 1, 0, 0, 1); if (soundId == 0) { soundId = mSoundPool.load(fullFilePath, 1); talkInfo.soundId = soundId; mPendingSound = soundId; } } else { final int soundId = mSoundPool.load(fullFilePath, 1); talkInfo.soundId = soundId; mPendingSound = soundId; } } else { HashMap<String, String> params = new HashMap<>(); try { ((PlaphoonsApplication) getApplication()).mTts.speak( talkInfo.text, mQueueMode, params); } catch (Exception ex) { // missing data, install it Intent installIntent = new Intent(); installIntent .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(installIntent); } } } } if (talkInfo.child != null) { // handle click on sample // TODO cache children and handle here as well MainActivity.this.showPanel(talkInfo.child, tiCollection); } else if (talkInfo.childFilename != null && talkInfo.childFilename.length() > 0) { mParentStack.add(mCurrentPlaFilename); mCurrentPlaFilename = talkInfo.childFilename; openPanel(); } } private void home() { mCurrentPlaFilename = null; openPanel(); } private void playText() { HashMap<String, String> params = new HashMap<String, String>(); try { ((PlaphoonsApplication) getApplication()).mTts.speak(mText .getText().toString(), mQueueMode, params); } catch (Exception ex) { // missing data, install it Intent installIntent = new Intent(); installIntent .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); startActivity(installIntent); } if (mPrintText && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { printText(); } } private void printText() { WebView webView = new WebView(this); webView.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } @Override public void onPageFinished(WebView view, String url) { Log.v("page finished loading " + url); createWebPrintJob(view); mWebView = null; } }); // Generate an HTML document on the fly: String htmlDocument = "<html><body><div style=\"overflow:auto\">"; for (int i = 0; i < mTextAsImages.getChildCount(); i++) { TalkButton btn = (TalkButton) mTextAsImages.getChildAt(i); htmlDocument += "<div style=\"height:150px;width:150px;float:left;\">"; htmlDocument += "<img style=\"max-height:100%;max-width:100%;\" src=\"file://" + mPlaRootDir + "/" + btn.mTalkInfo.drawablePath + "\"/>"; htmlDocument += "</div>"; } htmlDocument += "</div><p>" + mText.getText() + "</p>"; htmlDocument += "</body></html>"; Log.v(htmlDocument); webView.loadDataWithBaseURL(mPlaRootDir, htmlDocument, "text/HTML", "UTF-8", null); // Keep a reference to WebView object until you pass the PrintDocumentAdapter // to the PrintManager mWebView = webView; } private void createWebPrintJob(WebView webView) { // Get a PrintManager instance PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE); // Get a print adapter instance PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(); // Create a print job with name and adapter instance String jobName = getString(R.string.app_name) + " Document"; PrintJob printJob = printManager.print(jobName, printAdapter, new PrintAttributes.Builder().build()); // Save the job object for later status checking mPrintJobs.add(printJob); } private void deleteText() { mText.setText(""); mTextAsImages.removeAllViews(); mTextStack.clear(); } }