1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.googlecode.android_scripting.activity; 18 19import android.app.Activity; 20import android.content.Context; 21import android.content.Intent; 22import android.content.SharedPreferences; 23import android.net.Uri; 24import android.os.Bundle; 25import android.preference.PreferenceManager; 26import android.view.Gravity; 27import android.view.View; 28import android.view.Window; 29import android.view.View.OnClickListener; 30import android.view.ViewGroup.LayoutParams; 31import android.view.ViewGroup.MarginLayoutParams; 32import android.widget.Button; 33import android.widget.LinearLayout; 34 35import com.googlecode.android_scripting.AsyncTaskListener; 36import com.googlecode.android_scripting.InterpreterInstaller; 37import com.googlecode.android_scripting.InterpreterUninstaller; 38import com.googlecode.android_scripting.Log; 39import com.googlecode.android_scripting.exception.Sl4aException; 40import com.googlecode.android_scripting.interpreter.InterpreterConstants; 41import com.googlecode.android_scripting.interpreter.InterpreterDescriptor; 42 43/** 44 * Base activity for distributing interpreters as APK's. 45 * 46 */ 47public 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 58 protected abstract InterpreterDescriptor getDescriptor(); 59 60 protected abstract InterpreterInstaller getInterpreterInstaller(InterpreterDescriptor descriptor, 61 Context context, AsyncTaskListener<Boolean> listener) throws Sl4aException; 62 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 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 111 protected void onStop() { 112 super.onStop(); 113 finish(); 114 } 115 116 // TODO(alexey): Pull out to a layout XML? 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 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 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 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 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 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 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 204 protected boolean checkInstalled() { 205 boolean isInstalled = 206 mPreferences.getBoolean(InterpreterConstants.INSTALLED_PREFERENCE_KEY, false); 207 broadcastInstallationStateChange(isInstalled); 208 return isInstalled; 209 } 210 211 public LinearLayout getLayout() { 212 return mLayout; 213 } 214 215} 216