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 17 package com.googlecode.android_scripting.activity; 18 19 import android.app.AlertDialog; 20 import android.app.ListActivity; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.DialogInterface.OnClickListener; 24 import android.content.Intent; 25 import android.content.SharedPreferences; 26 import android.database.DataSetObserver; 27 import android.net.Uri; 28 import android.os.Bundle; 29 import android.preference.PreferenceManager; 30 import android.view.LayoutInflater; 31 import android.view.Menu; 32 import android.view.MenuItem; 33 import android.view.SubMenu; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.widget.BaseAdapter; 37 import android.widget.ImageView; 38 import android.widget.LinearLayout; 39 import android.widget.ListView; 40 import android.widget.TextView; 41 42 import com.googlecode.android_scripting.ActivityFlinger; 43 import com.googlecode.android_scripting.BaseApplication; 44 import com.googlecode.android_scripting.Constants; 45 import com.googlecode.android_scripting.FeaturedInterpreters; 46 import com.googlecode.android_scripting.R; 47 import com.googlecode.android_scripting.interpreter.Interpreter; 48 import com.googlecode.android_scripting.interpreter.InterpreterConfiguration; 49 import com.googlecode.android_scripting.interpreter.InterpreterConfiguration.ConfigurationObserver; 50 import com.googlecode.android_scripting.service.ScriptingLayerService; 51 52 import java.net.URL; 53 import java.util.ArrayList; 54 import java.util.List; 55 56 public class InterpreterManager extends ListActivity { 57 58 private InterpreterManagerAdapter mAdapter; 59 private InterpreterListObserver mObserver; 60 private List<Interpreter> mInterpreters; 61 private List<String> mFeaturedInterpreters; 62 private InterpreterConfiguration mConfiguration; 63 private SharedPreferences mPreferences; 64 65 private static enum MenuId { 66 HELP, ADD, NETWORK, PREFERENCES; getId()67 public int getId() { 68 return ordinal() + Menu.FIRST; 69 } 70 } 71 72 @Override onCreate(Bundle savedInstanceState)73 public void onCreate(Bundle savedInstanceState) { 74 super.onCreate(savedInstanceState); 75 CustomizeWindow.requestCustomTitle(this, "Interpreters", R.layout.interpreter_manager); 76 mConfiguration = ((BaseApplication) getApplication()).getInterpreterConfiguration(); 77 mInterpreters = new ArrayList<Interpreter>(); 78 mAdapter = new InterpreterManagerAdapter(); 79 mObserver = new InterpreterListObserver(); 80 mAdapter.registerDataSetObserver(mObserver); 81 setListAdapter(mAdapter); 82 ActivityFlinger.attachView(getListView(), this); 83 ActivityFlinger.attachView(getWindow().getDecorView(), this); 84 mFeaturedInterpreters = FeaturedInterpreters.getList(); 85 mPreferences = PreferenceManager.getDefaultSharedPreferences(this); 86 } 87 88 @Override onStart()89 public void onStart() { 90 super.onStart(); 91 mConfiguration.registerObserver(mObserver); 92 mAdapter.notifyDataSetInvalidated(); 93 } 94 95 @Override onResume()96 protected void onResume() { 97 super.onResume(); 98 mAdapter.notifyDataSetInvalidated(); 99 } 100 101 @Override onStop()102 public void onStop() { 103 super.onStop(); 104 mConfiguration.unregisterObserver(mObserver); 105 } 106 107 @Override onPrepareOptionsMenu(Menu menu)108 public boolean onPrepareOptionsMenu(Menu menu) { 109 menu.clear(); 110 buildInstallLanguagesMenu(menu); 111 menu.add(Menu.NONE, MenuId.NETWORK.getId(), Menu.NONE, "Start Server").setIcon( 112 android.R.drawable.ic_menu_share); 113 menu.add(Menu.NONE, MenuId.PREFERENCES.getId(), Menu.NONE, "Preferences").setIcon( 114 android.R.drawable.ic_menu_preferences); 115 return super.onPrepareOptionsMenu(menu); 116 } 117 buildInstallLanguagesMenu(Menu menu)118 private void buildInstallLanguagesMenu(Menu menu) { 119 SubMenu installMenu = 120 menu.addSubMenu(Menu.NONE, MenuId.ADD.getId(), Menu.NONE, "Add").setIcon( 121 android.R.drawable.ic_menu_add); 122 int i = MenuId.values().length + Menu.FIRST; 123 for (String interpreterName : mFeaturedInterpreters) { 124 installMenu.add(Menu.NONE, i++, Menu.NONE, interpreterName); 125 } 126 } 127 128 @Override onOptionsItemSelected(MenuItem item)129 public boolean onOptionsItemSelected(MenuItem item) { 130 int itemId = item.getItemId(); 131 if (itemId == MenuId.NETWORK.getId()) { 132 AlertDialog.Builder dialog = new AlertDialog.Builder(this); 133 dialog.setItems(new CharSequence[] { "Public", "Private" }, new OnClickListener() { 134 @Override 135 public void onClick(DialogInterface dialog, int which) { 136 launchService(which == 0 /* usePublicIp */); 137 } 138 }); 139 dialog.show(); 140 } else if (itemId == MenuId.PREFERENCES.getId()) { 141 startActivity(new Intent(this, Preferences.class)); 142 } else if (itemId >= MenuId.values().length + Menu.FIRST) { 143 int i = itemId - MenuId.values().length - Menu.FIRST; 144 if (i < mFeaturedInterpreters.size()) { 145 URL url = FeaturedInterpreters.getUrlForName(mFeaturedInterpreters.get(i)); 146 Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url.toString())); 147 startActivity(viewIntent); 148 } 149 } 150 return true; 151 } 152 getPrefInt(String key, int defaultValue)153 private int getPrefInt(String key, int defaultValue) { 154 int result = defaultValue; 155 String value = mPreferences.getString(key, null); 156 if (value != null) { 157 try { 158 result = Integer.parseInt(value); 159 } catch (NumberFormatException e) { 160 result = defaultValue; 161 } 162 } 163 return result; 164 } 165 launchService(boolean usePublicIp)166 private void launchService(boolean usePublicIp) { 167 Intent intent = new Intent(this, ScriptingLayerService.class); 168 intent.setAction(Constants.ACTION_LAUNCH_SERVER); 169 intent.putExtra(Constants.EXTRA_USE_EXTERNAL_IP, usePublicIp); 170 intent.putExtra(Constants.EXTRA_USE_SERVICE_PORT, getPrefInt("use_service_port", 0)); 171 startService(intent); 172 } 173 launchTerminal(Interpreter interpreter)174 private void launchTerminal(Interpreter interpreter) { 175 Intent intent = new Intent(this, ScriptingLayerService.class); 176 intent.setAction(Constants.ACTION_LAUNCH_INTERPRETER); 177 intent.putExtra(Constants.EXTRA_INTERPRETER_NAME, interpreter.getName()); 178 startService(intent); 179 } 180 181 @Override onListItemClick(ListView list, View view, int position, long id)182 protected void onListItemClick(ListView list, View view, int position, long id) { 183 Interpreter interpreter = (Interpreter) list.getItemAtPosition(position); 184 launchTerminal(interpreter); 185 } 186 187 @Override onDestroy()188 public void onDestroy() { 189 super.onDestroy(); 190 mConfiguration.unregisterObserver(mObserver); 191 } 192 193 private class InterpreterListObserver extends DataSetObserver implements ConfigurationObserver { 194 @Override onInvalidated()195 public void onInvalidated() { 196 mInterpreters = mConfiguration.getInteractiveInterpreters(); 197 } 198 199 @Override onChanged()200 public void onChanged() { 201 mInterpreters = mConfiguration.getInteractiveInterpreters(); 202 } 203 204 @Override onConfigurationChanged()205 public void onConfigurationChanged() { 206 runOnUiThread(new Runnable() { 207 @Override 208 public void run() { 209 mAdapter.notifyDataSetChanged(); 210 } 211 }); 212 } 213 } 214 215 private class InterpreterManagerAdapter extends BaseAdapter { 216 217 @Override getCount()218 public int getCount() { 219 return mInterpreters.size(); 220 } 221 222 @Override getItem(int position)223 public Object getItem(int position) { 224 return mInterpreters.get(position); 225 } 226 227 @Override getItemId(int position)228 public long getItemId(int position) { 229 return position; 230 } 231 232 @Override getView(int position, View convertView, ViewGroup parent)233 public View getView(int position, View convertView, ViewGroup parent) { 234 LinearLayout container; 235 236 Interpreter interpreter = mInterpreters.get(position); 237 238 if (convertView == null) { 239 LayoutInflater inflater = 240 (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 241 container = (LinearLayout) inflater.inflate(R.layout.list_item, null); 242 } else { 243 container = (LinearLayout) convertView; 244 } 245 ImageView img = (ImageView) container.findViewById(R.id.list_item_icon); 246 247 int imgId = 248 FeaturedInterpreters.getInterpreterIcon(InterpreterManager.this, 249 interpreter.getExtension()); 250 if (imgId == 0) { 251 imgId = R.drawable.sl4a_logo_32; 252 } 253 254 img.setImageResource(imgId); 255 256 TextView text = (TextView) container.findViewById(R.id.list_item_title); 257 258 text.setText(interpreter.getNiceName()); 259 return container; 260 } 261 } 262 } 263