1 /* 2 * Copyright (C) 2016 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.googlecode.android_scripting.activity; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.SharedPreferences; 23 import android.net.Uri; 24 import android.os.Bundle; 25 import android.preference.PreferenceManager; 26 import android.view.Gravity; 27 import android.view.View; 28 import android.view.Window; 29 import android.view.View.OnClickListener; 30 import android.view.ViewGroup.LayoutParams; 31 import android.view.ViewGroup.MarginLayoutParams; 32 import android.widget.Button; 33 import android.widget.LinearLayout; 34 35 import com.googlecode.android_scripting.AsyncTaskListener; 36 import com.googlecode.android_scripting.InterpreterInstaller; 37 import com.googlecode.android_scripting.InterpreterUninstaller; 38 import com.googlecode.android_scripting.Log; 39 import com.googlecode.android_scripting.exception.Sl4aException; 40 import com.googlecode.android_scripting.interpreter.InterpreterConstants; 41 import com.googlecode.android_scripting.interpreter.InterpreterDescriptor; 42 43 /** 44 * Base activity for distributing interpreters as APK's. 45 * 46 */ 47 public abstract class Main extends Activity { 48 49 protected final static float MARGIN_DIP = 3.0f; 50 51 protected final String mId = getClass().getPackage().getName(); 52 53 protected SharedPreferences mPreferences; 54 protected InterpreterDescriptor mDescriptor; 55 protected Button mButton; 56 protected LinearLayout mLayout; 57 getDescriptor()58 protected abstract InterpreterDescriptor getDescriptor(); 59 getInterpreterInstaller(InterpreterDescriptor descriptor, Context context, AsyncTaskListener<Boolean> listener)60 protected abstract InterpreterInstaller getInterpreterInstaller(InterpreterDescriptor descriptor, 61 Context context, AsyncTaskListener<Boolean> listener) throws Sl4aException; 62 getInterpreterUninstaller( InterpreterDescriptor descriptor, Context context, AsyncTaskListener<Boolean> listener)63 protected abstract InterpreterUninstaller getInterpreterUninstaller( 64 InterpreterDescriptor descriptor, Context context, AsyncTaskListener<Boolean> listener) 65 throws Sl4aException; 66 67 protected enum RunningTask { 68 INSTALL, UNINSTALL 69 } 70 71 protected volatile RunningTask mCurrentTask = null; 72 73 protected final AsyncTaskListener<Boolean> mTaskListener = new AsyncTaskListener<Boolean>() { 74 @Override 75 public void onTaskFinished(Boolean result, String message) { 76 getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, 77 Window.PROGRESS_VISIBILITY_OFF); 78 if (result) { 79 switch (mCurrentTask) { 80 case INSTALL: 81 setInstalled(true); 82 prepareUninstallButton(); 83 break; 84 case UNINSTALL: 85 setInstalled(false); 86 prepareInstallButton(); 87 break; 88 } 89 } 90 Log.v(Main.this, message); 91 mCurrentTask = null; 92 } 93 }; 94 95 @Override onCreate(Bundle savedInstanceState)96 protected void onCreate(Bundle savedInstanceState) { 97 super.onCreate(savedInstanceState); 98 mPreferences = PreferenceManager.getDefaultSharedPreferences(this); 99 mDescriptor = getDescriptor(); 100 101 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 102 initializeViews(); 103 if (checkInstalled()) { 104 prepareUninstallButton(); 105 } else { 106 prepareInstallButton(); 107 } 108 } 109 110 @Override onStop()111 protected void onStop() { 112 super.onStop(); 113 finish(); 114 } 115 116 // TODO(alexey): Pull out to a layout XML? initializeViews()117 protected void initializeViews() { 118 mLayout = new LinearLayout(this); 119 mLayout.setOrientation(LinearLayout.VERTICAL); 120 mLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 121 mLayout.setGravity(Gravity.CENTER_HORIZONTAL); 122 123 mButton = new Button(this); 124 MarginLayoutParams marginParams = 125 new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 126 final float scale = getResources().getDisplayMetrics().density; 127 int marginPixels = (int) (MARGIN_DIP * scale + 0.5f); 128 marginParams.setMargins(marginPixels, marginPixels, marginPixels, marginPixels); 129 mButton.setLayoutParams(marginParams); 130 mLayout.addView(mButton); 131 setContentView(mLayout); 132 } 133 prepareInstallButton()134 protected void prepareInstallButton() { 135 mButton.setText("Install"); 136 mButton.setOnClickListener(new OnClickListener() { 137 @Override 138 public void onClick(View v) { 139 install(); 140 } 141 }); 142 } 143 prepareUninstallButton()144 protected void prepareUninstallButton() { 145 mButton.setText("Uninstall"); 146 mButton.setOnClickListener(new OnClickListener() { 147 @Override 148 public void onClick(View v) { 149 uninstall(); 150 } 151 }); 152 } 153 broadcastInstallationStateChange(boolean isInterpreterInstalled)154 protected void broadcastInstallationStateChange(boolean isInterpreterInstalled) { 155 Intent intent = new Intent(); 156 intent.setData(Uri.parse("package:" + mId)); 157 if (isInterpreterInstalled) { 158 intent.setAction(InterpreterConstants.ACTION_INTERPRETER_ADDED); 159 } else { 160 intent.setAction(InterpreterConstants.ACTION_INTERPRETER_REMOVED); 161 } 162 sendBroadcast(intent); 163 } 164 install()165 protected synchronized void install() { 166 if (mCurrentTask != null) { 167 return; 168 } 169 getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, Window.PROGRESS_VISIBILITY_ON); 170 mCurrentTask = RunningTask.INSTALL; 171 InterpreterInstaller installTask; 172 try { 173 installTask = getInterpreterInstaller(mDescriptor, Main.this, mTaskListener); 174 } catch (Sl4aException e) { 175 Log.e(this, e.getMessage(), e); 176 return; 177 } 178 installTask.execute(); 179 } 180 uninstall()181 protected synchronized void uninstall() { 182 if (mCurrentTask != null) { 183 return; 184 } 185 getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, Window.PROGRESS_VISIBILITY_ON); 186 mCurrentTask = RunningTask.UNINSTALL; 187 InterpreterUninstaller uninstallTask; 188 try { 189 uninstallTask = getInterpreterUninstaller(mDescriptor, Main.this, mTaskListener); 190 } catch (Sl4aException e) { 191 Log.e(this, e.getMessage(), e); 192 return; 193 } 194 uninstallTask.execute(); 195 } 196 setInstalled(boolean isInstalled)197 protected void setInstalled(boolean isInstalled) { 198 SharedPreferences.Editor editor = mPreferences.edit(); 199 editor.putBoolean(InterpreterConstants.INSTALLED_PREFERENCE_KEY, isInstalled); 200 editor.commit(); 201 broadcastInstallationStateChange(isInstalled); 202 } 203 checkInstalled()204 protected boolean checkInstalled() { 205 boolean isInstalled = 206 mPreferences.getBoolean(InterpreterConstants.INSTALLED_PREFERENCE_KEY, false); 207 broadcastInstallationStateChange(isInstalled); 208 return isInstalled; 209 } 210 getLayout()211 public LinearLayout getLayout() { 212 return mLayout; 213 } 214 215 } 216