/*
HostCanvasProfile.java
Copyright (c) 2015 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.deviceplugin.host.activity;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import org.deviceconnect.android.deviceplugin.host.R;
import org.deviceconnect.android.deviceplugin.host.canvas.CanvasDrawImageObject;
import org.deviceconnect.android.deviceplugin.host.canvas.CanvasDrawUtils;
/**
* Canvas Profile Activity.
*
* @author NTT DOCOMO, INC.
*/
public class CanvasProfileActivity extends Activity {
/**
* Defined a parameter name.
*/
private static final String PARAM_INTENT = "param_intent";
/**
* Defined a dialog type:{@value}.
*/
private static final String DIALOG_TYPE_OOM = "TYPE_OOM";
/**
* Defined a dialog type:{@value}.
*/
private static final String DIALOG_TYPE_NOT_FOUND = "TYPE_NOT_FOUND";
/**
* 画像リソース取得結果.
*/
private enum ResourceResult {
/**
* リソースの取得に成功.
*/
Success,
/**
* リソースの取得時にOut Of Memoryが発生.
*/
OutOfMemory,
/**
* リソースの取得に失敗.
*/
NotFoundResource
}
/**
* Canvas view object.
*/
private ImageView mCanvasView;
/**
* Argument that draw in canvas.
*/
private Intent mIntent;
/**
* Bitmap that was sent from web application.
*/
private Bitmap mBitmap;
/**
* Download start dialog.
*/
private StartingDialogFragment mDialog;
/**
* Download flag.
*/
private boolean mDownloadFlag = false;
/**
* フォアグラウンドフラグ.
*/
private boolean mForegroundFlag = false;
/**
* 表示用オブジェクト.
*/
private CanvasDrawImageObject mDrawImageObject;
/**
* Implementation of BroadcastReceiver.
*/
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
String action = intent.getAction();
if (CanvasDrawImageObject.ACTION_DRAW_CANVAS.equals(action)) {
setDrawingArgument(intent);
refreshImage(intent);
} else if (CanvasDrawImageObject.ACTION_DELETE_CANVAS.equals(action)) {
finish();
}
}
};
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_canvas_profile);
mCanvasView = (ImageView) findViewById(R.id.canvasProfileView);
Button btn = (Button) findViewById(R.id.buttonClose);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
finish();
}
});
Intent intent = null;
if (savedInstanceState != null) {
intent = (Intent) savedInstanceState.get(PARAM_INTENT);
}
if (intent == null) {
intent = getIntent();
}
setDrawingArgument(intent);
}
@Override
protected void onResume() {
super.onResume();
mForegroundFlag = true;
IntentFilter filter = new IntentFilter();
filter.addAction(CanvasDrawImageObject.ACTION_DRAW_CANVAS);
filter.addAction(CanvasDrawImageObject.ACTION_DELETE_CANVAS);
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filter);
refreshImage(mIntent);
}
@Override
protected void onPause() {
mForegroundFlag = false;
dismissDownloadDialog();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
super.onPause();
}
@Override
protected void onSaveInstanceState(final Bundle outState) {
if (mIntent != null) {
outState.putParcelable(PARAM_INTENT, mIntent);
}
}
/**
* Set a argument that draw in canvas.
*
* @param intent argument
*/
private void setDrawingArgument(final Intent intent) {
if (intent != null) {
mIntent = intent;
}
}
/**
* リソースが見つからない場合のエラーダイアログを表示します.
*/
private void openNotFoundDrawImage() {
AlertDialogFragment oomDialog = AlertDialogFragment.create(DIALOG_TYPE_NOT_FOUND,
getString(R.string.host_canvas_error_title),
getString(R.string.host_canvas_error_not_found_message),
getString(R.string.host_ok));
oomDialog.show(getFragmentManager(), DIALOG_TYPE_NOT_FOUND);
}
/**
* メモリ不足エラーダイアログを表示します.
*/
private void openOutOfMemory() {
AlertDialogFragment oomDialog = AlertDialogFragment.create(DIALOG_TYPE_OOM,
getString(R.string.host_canvas_error_title),
getString(R.string.host_canvas_error_oom_message),
getString(R.string.host_ok));
oomDialog.show(getFragmentManager(), DIALOG_TYPE_OOM);
}
/**
* ダウンロードダイアログを表示します.
*/
private synchronized void showDownloadDialog() {
if (mDialog != null) {
mDialog.dismiss();
}
mDialog = new StartingDialogFragment();
mDialog.show(getFragmentManager(), "dialog");
}
/**
* ダウンロードダイアログを非表示にします.
*/
private synchronized void dismissDownloadDialog() {
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
}
/**
* 画面に表示する画像を更新します.
* @param intent 更新する画像データが入ったintent
*/
private void refreshImage(final Intent intent) {
final CanvasDrawImageObject drawImageObject = CanvasDrawImageObject.create(intent);
if (drawImageObject == null) {
openNotFoundDrawImage();
return;
}
if (mDownloadFlag) {
return;
}
mDownloadFlag = true;
AsyncTask<Void, ResourceResult, ResourceResult> task = new AsyncTask<Void, ResourceResult, ResourceResult>() {
@Override
protected void onPreExecute() {
showDownloadDialog();
}
@Override
protected ResourceResult doInBackground(final Void... params) {
if (mBitmap != null) {
// 同じデータへのURIならば、すでに画像を読み込んでいるの表示する
if (mDrawImageObject != null && drawImageObject.getData().equals(mDrawImageObject.getData())) {
return ResourceResult.Success;
} else {
mBitmap.recycle();
mBitmap = null;
}
}
String uri = drawImageObject.getData();
byte[] data;
try {
if (uri.startsWith("http")) {
data = CanvasDrawUtils.getData(uri);
} else if (uri.startsWith("content")) {
data = CanvasDrawUtils.getContentData(CanvasProfileActivity.this, uri);
} else {
data = CanvasDrawUtils.getCacheData(uri);
}
mBitmap = CanvasDrawUtils.getBitmap(data);
if (mBitmap == null) {
return ResourceResult.NotFoundResource;
}
} catch (OutOfMemoryError e) {
return ResourceResult.OutOfMemory;
} catch (Exception e) {
return ResourceResult.NotFoundResource;
}
return ResourceResult.Success;
}
@Override
protected void onPostExecute(final ResourceResult result) {
mDrawImageObject = drawImageObject;
dismissDownloadDialog();
if (mForegroundFlag) {
switch (result) {
case Success:
showDrawObject(mDrawImageObject);
break;
case OutOfMemory:
openOutOfMemory();
break;
case NotFoundResource:
openNotFoundDrawImage();
break;
}
}
mDownloadFlag = false;
}
};
task.execute();
}
/**
* 画面を更新します.
* @param drawObj 更新する画像データ
*/
private void showDrawObject(final CanvasDrawImageObject drawObj) {
switch (drawObj.getMode()) {
default:
case NON_SCALE_MODE:
Matrix matrix = new Matrix();
matrix.postTranslate((float) drawObj.getX(), (float) drawObj.getY());
mCanvasView.setImageBitmap(mBitmap);
mCanvasView.setScaleType(ScaleType.MATRIX);
mCanvasView.setImageMatrix(matrix);
break;
case SCALE_MODE:
mCanvasView.setImageBitmap(mBitmap);
mCanvasView.setScaleType(ScaleType.FIT_CENTER);
mCanvasView.setTranslationX((int) drawObj.getX());
mCanvasView.setTranslationY((int) drawObj.getY());
break;
case FILL_MODE:
BitmapDrawable bd = new BitmapDrawable(getResources(), mBitmap);
bd.setTileModeX(Shader.TileMode.REPEAT);
bd.setTileModeY(Shader.TileMode.REPEAT);
mCanvasView.setImageDrawable(bd);
mCanvasView.setScaleType(ScaleType.FIT_XY);
mCanvasView.setTranslationX((int) drawObj.getX());
mCanvasView.setTranslationY((int) drawObj.getY());
break;
}
}
/**
* Show a dialog of dwnload image.
*/
public static class StartingDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
String title = getString(R.string.host_canvas_download_title);
String msg = getString(R.string.host_canvas_download_message);
ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setTitle(title);
progressDialog.setMessage(msg);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
setCancelable(false);
return progressDialog;
}
@Override
public void onPause() {
dismiss();
super.onPause();
}
}
/**
* エラーダイアログ.
*/
public static class AlertDialogFragment extends DialogFragment {
/**
* タグのキーを定義します.
*/
private static final String KEY_TAG = "tag";
/**
* タイトルのキーを定義します.
*/
private static final String KEY_TITLE = "title";
/**
* メッセージのキーを定義します.
*/
private static final String KEY_MESSAGE = "message";
/**
* Positiveボタンのキーを定義します.
*/
private static final String KEY_POSITIVE = "yes";
/**
* Negativeボタンのキーを定義します.
*/
private static final String KEY_NEGATIVE = "no";
/**
* ボタン無しでAlertDialogを作成します.
* @param tag タグ
* @param title タイトル
* @param message メッセージ
* @return AlertDialogFragmentのインスタンス
*/
public static AlertDialogFragment create(final String tag, final String title, final String message) {
return create(tag, title, message, null, null);
}
/**
* PositiveボタンのみでAlertDialogを作成します.
* @param tag タグ
* @param title タイトル
* @param message メッセージ
* @param positive positiveボタン名
* @return AlertDialogFragmentのインスタンス
*/
public static AlertDialogFragment create(final String tag, final String title, final String message, final String positive) {
return create(tag, title, message, positive, null);
}
/**
* ボタン有りでAlertDialogを作成します.
* @param tag タグ
* @param title タイトル
* @param message メッセージ
* @param positive positiveボタン名
* @param negative negativeボタン名
* @return AlertDialogFragmentのインスタンス
*/
public static AlertDialogFragment create(final String tag, final String title, final String message,
final String positive, final String negative) {
Bundle args = new Bundle();
args.putString(KEY_TAG, tag);
args.putString(KEY_TITLE, title);
args.putString(KEY_MESSAGE, message);
if (positive != null) {
args.putString(KEY_POSITIVE, positive);
}
if (negative != null) {
args.putString(KEY_NEGATIVE, negative);
}
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.setArguments(args);
return dialog;
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(getArguments().getString(KEY_TITLE));
builder.setMessage(getArguments().getString(KEY_MESSAGE));
if (getArguments().getString(KEY_POSITIVE) != null) {
builder.setPositiveButton(getArguments().getString(KEY_POSITIVE),
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
Activity activity = getActivity();
if (activity != null) {
activity.finish();
}
}
});
}
if (getArguments().getString(KEY_NEGATIVE) != null) {
builder.setNegativeButton(getArguments().getString(KEY_NEGATIVE), null);
}
return builder.create();
}
@Override
public void onCancel(final DialogInterface dialog) {
}
}
}