/* CanvasProfile.java Copyright (c) 2014 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.deviceplugin.sw.profile; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import com.sonyericsson.extras.liveware.aef.control.Control; import com.sonyericsson.extras.liveware.extension.util.registration.DeviceInfoHelper; import org.deviceconnect.android.deviceplugin.sw.R; import org.deviceconnect.android.deviceplugin.sw.SWConstants; import org.deviceconnect.android.deviceplugin.sw.service.SWService; import org.deviceconnect.android.message.MessageUtils; import org.deviceconnect.android.profile.CanvasProfile; import org.deviceconnect.android.profile.api.DConnectApi; import org.deviceconnect.android.profile.api.PostApi; import org.deviceconnect.android.profile.util.CanvasProfileUtils; import org.deviceconnect.message.DConnectMessage; import java.io.ByteArrayOutputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * SonySWデバイスプラグインの{@link CanvasProfile}実装. * * @author NTT DOCOMO, INC. */ public class SWCanvasProfile extends CanvasProfile { private final ExecutorService mImageService = Executors.newSingleThreadExecutor(); private final DConnectApi mPostDrawImageApi = new PostApi() { @Override public String getAttribute() { return ATTRIBUTE_DRAW_IMAGE; } @Override public boolean onRequest(final Intent request, final Intent response) { final byte[] data = getData(request); final double x = getX(request); final double y = getY(request); final String mode = getMode(request); String mimeType = getMIMEType(request); if (mimeType != null && !mimeType.contains("image")) { MessageUtils.setInvalidRequestParameterError(response, "Unsupported mimeType: " + mimeType); return true; } if (data == null) { mImageService.execute(new Runnable() { @Override public void run() { String uri = getURI(request); byte[] result = getData(uri); if (result == null) { MessageUtils.setInvalidRequestParameterError(response, "could not get image from uri."); sendResponse(response); return; } drawImage(response, result, x, y, mode); sendResponse(response); } }); return false; } else { drawImage(response, data, x, y, mode); return true; } } }; /** * コンストラクタ. */ public SWCanvasProfile() { addApi(mPostDrawImageApi); } private void drawImage(final Intent response, byte[] data, double x, double y, String mode) { DisplaySize size = determineDisplaySize(getContext(), ((SWService) getService()).getHostPackageName()); boolean result = showDisplay(data, x, y, mode, size); if (!result) { /* unknown mode-value. */ MessageUtils.setInvalidRequestParameterError(response); return; } setResult(response, DConnectMessage.RESULT_OK); } /** * SWの画面に画像を表示する. * * @param data バイナリデータ * @param x x座標 * @param y y座標 * @param mode 画像描画モード * @param size 画面サイズ * @return true: success / false: error(unknown mode-value) */ private boolean showDisplay(final byte[] data, final double x, final double y, final String mode, final DisplaySize size) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inMutable = true; Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); // 最終的にSWに表示するBitmapの作成(大きさはSWの画面サイズ) final int width = size.getWidth(); final int height = size.getHeight(); Bitmap viewBitmap = Bitmap.createBitmap(width, height, SWConstants.DEFAULT_BITMAP_CONFIG); boolean isDraw = false; if (mode == null || mode.equals("")) { // 等倍描画モード CanvasProfileUtils.drawImageForNonScalesMode(viewBitmap, bitmap, x, y); isDraw = true; } else if (mode.equals(Mode.SCALES.getValue())) { // スケールモード CanvasProfileUtils.drawImageForScalesMode(viewBitmap, bitmap); isDraw = true; } else if (mode.equals(Mode.FILLS.getValue())) { // フィルモード CanvasProfileUtils.drawImageForFillsMode(viewBitmap, bitmap); isDraw = true; } if (isDraw) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(SWConstants.OUTPUTSTREAM_SIZE); viewBitmap.compress(CompressFormat.JPEG, SWConstants.BITMAP_DECODE_QUALITY, outputStream); Intent intent = new Intent(Control.Intents.CONTROL_DISPLAY_DATA_INTENT); intent.putExtra(Control.Intents.EXTRA_DATA, outputStream.toByteArray()); sendToHostApp(intent); return true; } else { return false; } } /** * 指定されたホストアプリケーションに対応するSWの画面サイズを返す. * * @param context コンテキスト * @param hostAppPackageName ホストアプリケーション名(SW1orSW2) * @return 画面サイズ */ private static DisplaySize determineDisplaySize(final Context context, final String hostAppPackageName) { boolean smartWatch2Supported = DeviceInfoHelper.isSmartWatch2ApiAndScreenDetected(context, hostAppPackageName); int width; int height; if (smartWatch2Supported) { width = context.getResources().getDimensionPixelSize(R.dimen.smart_watch_2_control_width); height = context.getResources().getDimensionPixelSize(R.dimen.smart_watch_2_control_height); } else { width = context.getResources().getDimensionPixelSize(R.dimen.smart_watch_control_width); height = context.getResources().getDimensionPixelSize(R.dimen.smart_watch_control_height); } return new DisplaySize(width, height); } private void sendToHostApp(final Intent request) { ((SWService) getService()).sendRequest(request); } }