Java tutorial
/* * Copyright 2016 Mobicage NV * * 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. * * @@license_version:1.1@@ */ package com.mobicage.rogerthat.plugins.messaging; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.net.URLEncoder; import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.params.HttpClientParams; import org.json.simple.JSONValue; import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.media.MediaPlayer; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.view.View; import android.view.WindowManager; import android.webkit.WebChromeClient; import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.MediaController; import android.widget.TextView; import android.widget.Toast; import android.widget.VideoView; import com.mobicage.rogerth.at.R; import com.mobicage.rogerthat.ServiceBoundActivity; import com.mobicage.rogerthat.util.TextUtils; import com.mobicage.rogerthat.util.http.HTTPUtil; import com.mobicage.rogerthat.util.logging.L; import com.mobicage.rogerthat.util.system.SafeAsyncTask; import com.mobicage.rogerthat.util.system.SafeDialogInterfaceOnClickListener; import com.mobicage.rogerthat.util.system.SystemUtils; import com.mobicage.rogerthat.util.system.T; import com.mobicage.rogerthat.util.ui.UIUtils; public class AttachmentViewerActivity extends ServiceBoundActivity { private final int DOWNLOAD_SUCCESS = 0; private final int DOWNLOAD_FAILED = 1; private final int DOWNLOAD_CANCELLED = 2; private class DownloadTask extends SafeAsyncTask<String, Integer, Integer> { private AttachmentViewerActivity mContext; private PowerManager.WakeLock mWakeLock; public DownloadTask(AttachmentViewerActivity context) { this.mContext = context; } @Override protected void safeOnCancelled(Integer result) { L.d("onCancelled: " + result); onPostExecute(mContext.DOWNLOAD_CANCELLED); } @Override protected Integer safeDoInBackground(String... params) { final String url = params[0]; try { final HttpClient httpClient = HTTPUtil.getHttpClient(0, 0); // no timeout HttpClientParams.setRedirecting(httpClient.getParams(), true); final HttpGet httpGet = new HttpGet(url); if (isCancelled()) { return mContext.DOWNLOAD_CANCELLED; } final HttpResponse response = httpClient.execute(httpGet); if (isCancelled()) { return mContext.DOWNLOAD_CANCELLED; } final int statusCode = response.getStatusLine().getStatusCode(); L.d(url + " --> status code: " + statusCode); if (statusCode != HttpStatus.SC_OK) { return mContext.DOWNLOAD_FAILED; } final HttpEntity responseEntity = response.getEntity(); final long fileLength = responseEntity.getContentLength(); final InputStream input = responseEntity.getContent(); try { final OutputStream output = new FileOutputStream(mFile); try { final byte data[] = new byte[4096]; long total = 0; int count; while ((count = input.read(data)) != -1) { if (isCancelled()) { return mContext.DOWNLOAD_CANCELLED; } total += count; if (fileLength > 0) publishProgress((int) (total * 100 / fileLength)); output.write(data, 0, count); } } finally { output.close(); } } finally { input.close(); } } catch (IOException e) { L.e(e); return mContext.DOWNLOAD_FAILED; } return mContext.DOWNLOAD_SUCCESS; } @Override protected void safeOnPreExecute() { // take CPU lock to prevent CPU from going off if the user // presses the power button during download PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName()); mWakeLock.acquire(); mProgressDialog.show(); } @Override protected void safeOnProgressUpdate(Integer... progress) { mProgressDialog.setIndeterminate(false); mProgressDialog.setMax(100); mProgressDialog.setProgress(progress[0]); } @Override protected void safeOnPostExecute(Integer result) { mWakeLock.release(); mProgressDialog.dismiss(); L.d("onPostExecute: " + result); if (result == mContext.DOWNLOAD_FAILED) { AlertDialog.Builder builder = new AlertDialog.Builder(mContext); builder.setMessage(R.string.error_please_try_again); builder.setCancelable(true); builder.setTitle(null); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { dialog.dismiss(); mContext.finish(); } }); builder.setPositiveButton(R.string.rogerthat, new SafeDialogInterfaceOnClickListener() { @Override public void safeOnClick(DialogInterface dialog, int which) { dialog.dismiss(); mContext.finish(); } }); builder.create().show(); removeAttachment(); } else if (result == mContext.DOWNLOAD_CANCELLED) { removeAttachment(); mContext.finish(); } else { Toast.makeText(mContext, R.string.file_downloaded, Toast.LENGTH_SHORT).show(); updateView(false); } } private void removeAttachment() { if (mFile.exists() && !SystemUtils.deleteDir(mFile)) { L.bug("Could not delete attachment file. threadKey: " + mThreadKey + " messageKey: " + mMessageKey + " downloadUrl: " + mDownloadUrl); } } } public final static String CONTENT_TYPE_JPEG = "image/jpeg"; public final static String CONTENT_TYPE_PNG = "image/png"; public final static String CONTENT_TYPE_PDF = "application/pdf"; public final static String CONTENT_TYPE_VIDEO_QUICKTIME = "video/quicktime"; // deprecated public final static String CONTENT_TYPE_VIDEO_MP4 = "video/mp4"; private final static List<String> SUPPORTED_CONTENT_TYPES = Arrays.asList(CONTENT_TYPE_JPEG, CONTENT_TYPE_PNG, CONTENT_TYPE_PDF, CONTENT_TYPE_VIDEO_QUICKTIME, CONTENT_TYPE_VIDEO_MP4); private MessagingPlugin mMessagingPlugin; private String mThreadKey; private String mMessageKey; private String mContentType; private String mDownloadUrl; private String mName; private File mAttachmentsDir; private String mDownloadUrlHash; private boolean mGenerateThumbnail; private File mFile; private WebView mWebview; private VideoView mVideoview; private ProgressDialog mProgressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected void onPause() { if (mVideoview != null) { mVideoview.pause(); } super.onPause(); } @Override protected void onServiceBound() { T.UI(); mProgressDialog = new ProgressDialog(AttachmentViewerActivity.this); mProgressDialog.setMessage(mService.getString(R.string.downloading)); mProgressDialog.setIndeterminate(true); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setCancelable(true); mMessagingPlugin = mService.getPlugin(MessagingPlugin.class); final Intent intent = getIntent(); mThreadKey = intent.getStringExtra("thread_key"); mMessageKey = intent.getStringExtra("message"); mContentType = intent.getStringExtra("content_type"); mDownloadUrl = intent.getStringExtra("download_url"); mName = intent.getStringExtra("name"); mDownloadUrlHash = intent.getStringExtra("download_url_hash"); mGenerateThumbnail = intent.getBooleanExtra("generate_thumbnail", false); if (mContentType.toLowerCase(Locale.US).startsWith("video/")) { setContentView(R.layout.file_viewer_video); mVideoview = (VideoView) findViewById(R.id.videoView); } else { getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); setContentView(R.layout.file_viewer); mWebview = (WebView) findViewById(R.id.webview); mWebview.setWebChromeClient(new WebChromeClient() { @Override public void onConsoleMessage(String message, int lineNumber, String sourceID) { if (sourceID != null) { try { sourceID = new File(sourceID).getName(); } catch (Exception e) { L.d("Could not get fileName of sourceID: " + sourceID, e); } } L.d(sourceID + ":" + lineNumber + " | " + message); } }); mWebview.setWebViewClient(new WebViewClient() { @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { L.d(failingUrl + ":" + errorCode + " | " + description); } }); final TextView titleTextView = (TextView) findViewById(R.id.title); if (TextUtils.isEmptyOrWhitespace(mName)) { titleTextView.setVisibility(View.GONE); findViewById(R.id.divider).setVisibility(View.GONE); } else { titleTextView.setVisibility(View.VISIBLE); titleTextView.setText(mName); findViewById(R.id.divider).setVisibility(View.VISIBLE); } } try { mAttachmentsDir = mMessagingPlugin.attachmentsDir(mThreadKey, null); } catch (IOException e) { L.d("Unable to create attachment directory", e); UIUtils.showAlertDialog(this, "", R.string.unable_to_read_write_sd_card); return; } mFile = new File(mAttachmentsDir, mDownloadUrlHash); if (mMessagingPlugin.attachmentExists(mAttachmentsDir, mDownloadUrlHash)) { updateView(false); } else { try { mAttachmentsDir = mMessagingPlugin.attachmentsDir(mThreadKey, mMessageKey); } catch (IOException e) { L.d("Unable to create attachment directory", e); UIUtils.showAlertDialog(this, "", R.string.unable_to_read_write_sd_card); return; } mFile = new File(mAttachmentsDir, mDownloadUrlHash); if (mMessagingPlugin.attachmentExists(mAttachmentsDir, mDownloadUrlHash)) { updateView(false); } else { downloadAttachment(); } } } @Override protected void onServiceUnbound() { T.UI(); } @Override protected void onDestroy() { super.onDestroy(); } @Override public void finish() { if (mWebview != null) { // Stop all javascript mWebview.loadUrl("about:blank"); } super.finish(); } @SuppressLint({ "SetJavaScriptEnabled" }) protected void updateView(boolean isUpdate) { T.UI(); if (!isUpdate && mGenerateThumbnail) { File thumbnail = new File(mFile.getAbsolutePath() + ".thumb"); if (!thumbnail.exists()) { boolean isImage = mContentType.toLowerCase(Locale.US).startsWith("image/"); boolean isVideo = !isImage && mContentType.toLowerCase(Locale.US).startsWith("video/"); try { // Try to generate a thumbnail mMessagingPlugin.createAttachmentThumbnail(mFile.getAbsolutePath(), isImage, isVideo); } catch (Exception e) { L.e("Failed to generate attachment thumbnail", e); } } } final String fileOnDisk = "file://" + mFile.getAbsolutePath(); if (mContentType.toLowerCase(Locale.US).startsWith("video/")) { MediaController mediacontroller = new MediaController(this); mediacontroller.setAnchorView(mVideoview); Uri video = Uri.parse(fileOnDisk); mVideoview.setMediaController(mediacontroller); mVideoview.setVideoURI(video); mVideoview.requestFocus(); mVideoview.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mVideoview.start(); } }); mVideoview.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { L.e("Could not play video, what " + what + ", extra " + extra + ", content_type " + mContentType + ", and url " + mDownloadUrl); AlertDialog.Builder builder = new AlertDialog.Builder(AttachmentViewerActivity.this); builder.setMessage(R.string.error_please_try_again); builder.setCancelable(true); builder.setTitle(null); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { dialog.dismiss(); finish(); } }); builder.setPositiveButton(R.string.rogerthat, new SafeDialogInterfaceOnClickListener() { @Override public void safeOnClick(DialogInterface dialog, int which) { dialog.dismiss(); finish(); } }); builder.create().show(); return true; } }); } else if (CONTENT_TYPE_PDF.equalsIgnoreCase(mContentType)) { WebSettings settings = mWebview.getSettings(); settings.setJavaScriptEnabled(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { settings.setAllowUniversalAccessFromFileURLs(true); } mWebview.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { if (fileOnDisk.equals(url)) { return null; } L.d("404: Expected: '" + fileOnDisk + "'\n Received: '" + url + "'"); return new WebResourceResponse("text/plain", "UTF-8", null); } }); try { mWebview.loadUrl("file:///android_asset/pdfjs/web/viewer.html?file=" + URLEncoder.encode(fileOnDisk, "UTF-8")); } catch (UnsupportedEncodingException uee) { L.bug(uee); } } else { WebSettings settings = mWebview.getSettings(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { settings.setAllowFileAccessFromFileURLs(true); } settings.setBuiltInZoomControls(true); settings.setLoadWithOverviewMode(true); settings.setUseWideViewPort(true); if (mContentType.toLowerCase(Locale.US).startsWith("image/")) { String html = "<html><head></head><body><img style=\"width: 100%;\" src=\"" + fileOnDisk + "\"></body></html>"; mWebview.loadDataWithBaseURL("", html, "text/html", "utf-8", ""); } else { mWebview.loadUrl(fileOnDisk); } } L.d("File on disk: " + fileOnDisk); } public static boolean supportsContentType(String contentType) { return SUPPORTED_CONTENT_TYPES.contains(contentType); } private void downloadAttachment() { final DownloadTask downloadTask = new DownloadTask(AttachmentViewerActivity.this); downloadTask.execute(mDownloadUrl); mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { L.d("mProgressDialog.setOnCancelListener"); downloadTask.cancel(true); } }); } }