package org.odk.collect.android.views.media; import java.io.File; import org.javarosa.core.reference.InvalidReferenceException; import org.javarosa.core.reference.ReferenceManager; import org.odk.collect.android.R; import org.odk.collect.android.preferences.PreferencesActivity; import org.odk.collect.android.utilities.FileUtils; import org.odk.collect.android.utilities.QRCodeEncoder; import org.odk.collect.android.views.ResizingImageView; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.net.Uri; import android.preference.PreferenceManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; /** * This layout is used anywhere we can have image/audio/video/text. TODO: It would probably be nice * to put this in a layout.xml file of some sort at some point. * * @author carlhartung */ public class MediaLayout extends RelativeLayout { private static final String t = "AVTLayout"; private TextView mView_Text; private AudioButton mAudioButton; private ImageButton mVideoButton; private ResizingImageView mImageView; private TextView mMissingImage; private int minimumHeight =-1; private int maximumHeight =-1; public MediaLayout(Context c) { super(c); mView_Text = null; mAudioButton = null; mImageView = null; mMissingImage = null; mVideoButton = null; } protected void onHelpPressed() { } public void setAVT(TextView text, String audioURI, String imageURI, final String videoURI, final String bigImageURI) { setAVT(text, audioURI, imageURI, videoURI, bigImageURI, null); } public void setAVT(TextView text, String audioURI, String imageURI, final String videoURI, final String bigImageURI, final String qrCodeContent) { mView_Text = text; // Layout configurations for our elements in the relative layout RelativeLayout.LayoutParams textParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams audioParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); imageParams.addRule(CENTER_IN_PARENT); RelativeLayout.LayoutParams videoParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams topPaneParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); RelativeLayout topPane = new RelativeLayout(this.getContext()); topPane.setId(2342134); this.addView(topPane, topPaneParams); // First set up the audio button if (audioURI != null) { // An audio file is specified mAudioButton = new AudioButton(getContext(), audioURI, true); mAudioButton.setId(3245345); // random ID to be used by the relative layout. } else { // No audio file specified, so ignore. } // Then set up the video button if (videoURI != null && videoURI.equals("help")) { // Magic Help backdoor! mVideoButton = new ImageButton(getContext()); mVideoButton.setImageResource(android.R.drawable.ic_menu_help); mVideoButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { MediaLayout.this.onHelpPressed(); } }); mVideoButton.setId(234982340); } // Then set up the video button else if (videoURI != null) { // An audio file is specified mVideoButton = new ImageButton(getContext()); mVideoButton.setImageResource(android.R.drawable.ic_media_play); mVideoButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String videoFilename = ""; try { videoFilename = ReferenceManager._().DeriveReference(videoURI).getLocalURI(); } catch (InvalidReferenceException e) { Log.e(t, "Invalid reference exception"); e.printStackTrace(); } File videoFile = new File(videoFilename); if (!videoFile.exists()) { // We should have a video clip, but the file doesn't exist. String errorMsg = getContext().getString(R.string.file_missing, videoFilename); Log.e(t, errorMsg); Toast.makeText(getContext(), errorMsg, Toast.LENGTH_LONG).show(); return; } Intent i = new Intent("android.intent.action.VIEW"); i.setDataAndType(Uri.fromFile(videoFile), "video/*"); try { ((Activity) getContext()).startActivity(i); } catch (ActivityNotFoundException e) { Toast.makeText(getContext(), getContext().getString(R.string.activity_not_found, "view video"), Toast.LENGTH_SHORT); } } }); mVideoButton.setId(234982340); } else { // No video file specified, so ignore. } // Add the audioButton and videoButton (if applicable) and view (containing text) to the // relative layout. if (mAudioButton != null && mVideoButton == null) { audioParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); textParams.addRule(RelativeLayout.LEFT_OF, mAudioButton.getId()); topPane.addView(mAudioButton, audioParams); } else if (mAudioButton == null && mVideoButton != null) { videoParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); textParams.addRule(RelativeLayout.LEFT_OF, mVideoButton.getId()); topPane.addView(mVideoButton, videoParams); } else if (mAudioButton != null && mVideoButton != null) { audioParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); textParams.addRule(RelativeLayout.LEFT_OF, mAudioButton.getId()); videoParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); videoParams.addRule(RelativeLayout.BELOW, mAudioButton.getId()); topPane.addView(mAudioButton, audioParams); topPane.addView(mVideoButton, videoParams); } boolean textVisible = (text.getVisibility() != GONE); if (textVisible) { textParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); topPane.addView(text, textParams); } // Now set up the image view String errorMsg = null; View imageView= null; if(qrCodeContent != null ) { Bitmap image; Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); //see if we're doing a new QR code display if(qrCodeContent != null) { int screenWidth = display.getWidth(); int screenHeight = display.getHeight(); int minimumDim = Math.min(screenWidth, screenHeight); try { QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrCodeContent,minimumDim); image = qrCodeEncoder.encodeAsBitmap(); mImageView = new ResizingImageView(getContext()); mImageView.setPadding(10, 10, 10, 10); mImageView.setAdjustViewBounds(true); mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); mImageView.setImageBitmap(image); mImageView.setId(23423534); //mImageView.resizeMaxMin(minimumHeight, maximumHeight); imageView = mImageView; } catch(Exception e) { e.printStackTrace(); } } } else if (imageURI != null) { try { DisplayMetrics metrics = this.getContext().getResources().getDisplayMetrics(); int maxWidth = metrics.widthPixels; int maxHeight = metrics.heightPixels; // subtract height for textviewa and buttons, if present if(mView_Text != null){ maxHeight = maxHeight - mView_Text.getHeight(); } if(mVideoButton != null){ maxHeight = maxHeight - mVideoButton.getHeight(); } else if(mAudioButton != null){ maxHeight = maxHeight - mAudioButton.getHeight(); } // reduce by third for safety maxHeight = (2 * maxHeight)/3; //If we didn't get an image yet, try for a norm final String imageFilename = ReferenceManager._().DeriveReference(imageURI).getLocalURI(); final File imageFile = new File(imageFilename); if (imageFile.exists()) { Bitmap b = null; try { Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); int screenWidth = display.getWidth(); int screenHeight = display.getHeight(); b = FileUtils .getBitmapScaledToDisplay(imageFile, screenHeight, screenWidth); } catch (OutOfMemoryError e) { errorMsg = "ERROR: " + e.getMessage(); } if (b != null) { mImageView = new ResizingImageView(getContext(), imageURI, bigImageURI); mImageView.setPadding(10, 10, 10, 10); mImageView.setAdjustViewBounds(true); if(ResizingImageView.resizeMethod.equals("full") || ResizingImageView.resizeMethod.equals("half")){ mImageView.setMaxHeight(maxHeight); mImageView.setMaxWidth(maxWidth); } mImageView.setImageBitmap(b); mImageView.setId(23423534); imageView = mImageView; } else if (errorMsg == null) { // An error hasn't been logged and loading the image failed, so it's likely // a bad file. errorMsg = getContext().getString(R.string.file_invalid, imageFile); } } else if (errorMsg == null) { // An error hasn't been logged. We should have an image, but the file doesn't // exist. errorMsg = getContext().getString(R.string.file_missing, imageFile); } if (errorMsg != null) { // errorMsg is only set when an error has occured Log.e(t, errorMsg); mMissingImage = new TextView(getContext()); mMissingImage.setText(errorMsg); mMissingImage.setPadding(10, 10, 10, 10); mMissingImage.setId(234873453); imageView = mMissingImage; } } catch (InvalidReferenceException e) { Log.e(t, "image invalid reference exception"); e.printStackTrace(); } } if(imageView != null) { RelativeLayout parent = this; imageParams.addRule(RelativeLayout.BELOW, topPane.getId()); if (mAudioButton != null) { if (!textVisible) { imageParams.addRule(RelativeLayout.LEFT_OF, mAudioButton.getId()); parent = topPane; } } if (mVideoButton != null) { if (!textVisible) { imageParams.addRule(RelativeLayout.LEFT_OF, mVideoButton.getId()); parent = topPane; } } parent.addView(imageView, imageParams); } } /** * This adds a divider at the bottom of this layout. Used to separate fields in lists. * * @param v */ public void addDivider(ImageView v) { RelativeLayout.LayoutParams dividerParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); if (mImageView != null) { dividerParams.addRule(RelativeLayout.BELOW, mImageView.getId()); } else if (mMissingImage != null) { dividerParams.addRule(RelativeLayout.BELOW, mMissingImage.getId()); } else if (mVideoButton != null) { dividerParams.addRule(RelativeLayout.BELOW, mVideoButton.getId()); } else if (mAudioButton != null) { dividerParams.addRule(RelativeLayout.BELOW, mAudioButton.getId()); } else if (mView_Text != null) { // No picture dividerParams.addRule(RelativeLayout.BELOW, mView_Text.getId()); } else { Log.e(t, "Tried to add divider to uninitialized ATVWidget"); return; } addView(v, dividerParams); } @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); if (visibility != View.VISIBLE) { if (mAudioButton != null) { mAudioButton.endPlaying(); } } } }