1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 package org.skia.viewer; 9 10 import android.app.Application; 11 import android.content.Intent; 12 import android.content.res.AssetManager; 13 import java.nio.ByteBuffer; 14 import java.nio.charset.StandardCharsets; 15 16 public class ViewerApplication extends Application { 17 private long mNativeHandle = 0; 18 private ViewerActivity mViewerActivity; 19 private String mStateJsonStr, mTitle; 20 21 static { 22 System.loadLibrary("viewer"); 23 } 24 createNativeApp(AssetManager assetManager, ByteBuffer[] args)25 private native long createNativeApp(AssetManager assetManager, ByteBuffer[] args); destroyNativeApp(long handle)26 private native void destroyNativeApp(long handle); 27 28 @Override onTerminate()29 public void onTerminate() { 30 if (mNativeHandle != 0) { 31 destroyNativeApp(mNativeHandle); 32 mNativeHandle = 0; 33 } 34 super.onTerminate(); 35 } 36 getNativeHandle()37 public long getNativeHandle() { 38 return mNativeHandle; 39 } 40 setViewerActivity(ViewerActivity viewerActivity)41 public void setViewerActivity(ViewerActivity viewerActivity) { 42 mViewerActivity = viewerActivity; 43 // Note that viewerActivity might be null (called by onDestroy) 44 if (mViewerActivity != null) { 45 // A new ViewerActivity is created; initialize its state and title 46 if (mStateJsonStr != null) { 47 mViewerActivity.setState(mStateJsonStr); 48 } 49 if (mTitle != null) { 50 mViewerActivity.setTitle(mTitle); 51 } 52 if (mNativeHandle == 0) { 53 final ByteBuffer[] byteBufferArgs; 54 Intent intent = viewerActivity.getIntent(); 55 String args = intent.getStringExtra("args"); 56 if (args == null) { 57 byteBufferArgs = new ByteBuffer[0]; 58 } else { 59 //TODO: split args better? 60 String[] splitArgs = args.split("\\s+"); 61 byteBufferArgs = new ByteBuffer[splitArgs.length]; 62 for (int i = 0; i < splitArgs.length; ++i) { 63 ByteBuffer bbArg = StandardCharsets.UTF_8.encode(splitArgs[i]); 64 ByteBuffer directBBArg = ByteBuffer.allocateDirect(bbArg.limit() + 1); 65 for (int j = 0; j < bbArg.limit(); ++j) { 66 directBBArg.put(j, bbArg.get(j)); 67 } 68 // UTF-8 doens't allow a zero terminator, but args require it. 69 directBBArg.put(bbArg.limit(), (byte)0); 70 byteBufferArgs[i] = directBBArg; 71 } 72 } 73 mNativeHandle = createNativeApp(this.getResources().getAssets(), byteBufferArgs); 74 } 75 } 76 } 77 setTitle(String title)78 public void setTitle(String title) { 79 mTitle = title; // Similar to mStateJsonStr, we have to store this. 80 if (mTitle.startsWith("Viewer: ")) { // Quick hack to shorten the title 81 mTitle = mTitle.replaceFirst("Viewer: ", ""); 82 } 83 if (mViewerActivity != null) { 84 mViewerActivity.runOnUiThread(new Runnable() { 85 @Override 86 public void run() { 87 mViewerActivity.setTitle(mTitle); 88 } 89 }); 90 } 91 } 92 setState(String stateJsonStr)93 public void setState(String stateJsonStr) { 94 // We have to store this state because ViewerActivity may be destroyed while the native app 95 // is still running. When a new ViewerActivity is created, we'll pass the state to it. 96 mStateJsonStr = stateJsonStr; 97 if (mViewerActivity != null) { 98 mViewerActivity.runOnUiThread(new Runnable() { 99 @Override 100 public void run() { 101 mViewerActivity.setState(mStateJsonStr); 102 } 103 }); 104 } 105 } 106 } 107