package cri.sanity; import java.io.File; import java.io.FilenameFilter; import java.util.Arrays; import java.util.Map; import java.util.Vector; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.media.AudioManager; import android.os.Bundle; import android.util.Pair; import cri.sanity.screen.*; import cri.sanity.util.*; public final class ShortcutActivity extends Activity implements DialogInterface.OnDismissListener, FilenameFilter { public static final String EXTRA_KEY = "cri.sanity.shortcut"; private static final String EXTRA_KEY2 = "cri.sanity.shortcut2"; private static final String EXTRA_KEY3 = "cri.sanity.shortcut3"; private static final String EXTRA_OPTION = "option"; private static final String EXTRA_ALARMER = "alarmer"; private static final String EXTRA_PRF = "profile"; private static final String EXTRA_REC = "rec_srv"; private static final String EXTRA_FILTER = "filter"; private static final String EXTRA_SCREEN = "screen"; private static final String SHORTCUT_PREFIX = "[S] "; private static final int SHORTCUT_ROW = 4; private static final int SHORTCUT_FILTER_ROW = PrefGroups.SHORTCUT_FILTER_ROW; private boolean skipQuit = false; // SHORTCUT_ROW contains how many values are in one row! private static Object[] getShortcuts() { return new Object[] { R.string.option_shortcut , 0 , EXTRA_OPTION , null, R.string.filter_cat , 0 , EXTRA_FILTER , null, R.string.silent_shortcut , R.drawable.ic_silent , EXTRA_ALARMER , Alarmer.ACT_SILENTLIMIT, R.string.airplane_shortcut , R.drawable.ic_airplane , EXTRA_ALARMER , Alarmer.ACT_FLIGHTOFF, R.string.profile_shortcut , R.drawable.ic_prf , EXTRA_PRF , null, R.string.profile_cat , R.drawable.menu_profiles , EXTRA_SCREEN , ProfileActivity.class.getName(), R.string.general_cat , R.drawable.menu_general , EXTRA_SCREEN , GeneralActivity.class.getName(), R.string.devices_cat , R.drawable.menu_devices , EXTRA_SCREEN , DevicesActivity.class.getName(), R.string.proximity_cat , R.drawable.menu_proximity, EXTRA_SCREEN , ProximityActivity.class.getName(), R.string.speaker_cat , R.drawable.menu_speaker , EXTRA_SCREEN , SpeakerActivity.class.getName(), R.string.vol_cat , R.drawable.menu_vol , EXTRA_SCREEN , VolumeActivity.class.getName(), R.string.notify_cat , R.drawable.menu_notify , EXTRA_SCREEN , NotifyActivity.class.getName(), R.string.vibrate_cat , R.drawable.menu_vibra , EXTRA_SCREEN , VibraActivity.class.getName(), R.string.block_cat , R.drawable.menu_block , EXTRA_SCREEN , BlockerActivity.class.getName(), R.string.tts_cat , R.drawable.menu_tts , EXTRA_SCREEN , TtsActivity.class.getName(), R.string.urgent_cat , R.drawable.menu_urgent , EXTRA_SCREEN , UrgentActivity.class.getName(), R.string.answer_cat , R.drawable.menu_answer , EXTRA_SCREEN , AnswerActivity.class.getName(), R.string.anonym_cat , R.drawable.menu_anonym , EXTRA_SCREEN , AnonymActivity.class.getName(), R.string.rec_cat , R.drawable.menu_rec , EXTRA_SCREEN , RecordActivity.class.getName(), R.string.rec_shortcut , R.drawable.ic_rec_now , EXTRA_REC , null, R.string.rec_browse_title , R.drawable.menu_browse , EXTRA_SCREEN , BrowseActivity.class.getName(), R.string.history_call , R.drawable.menu_block , EXTRA_SCREEN , CallHistoryActivity.class.getName(), R.string.history_sms , R.drawable.menu_block , EXTRA_SCREEN , SmsHistoryActivity.class.getName(), R.string.about_cat , R.drawable.menu_about , EXTRA_SCREEN , AboutActivity.class.getName(), }; } // SHORTCUT_FILTER_ROW contains how many values are in one row! private static Object[] getFilterShortcuts() { return PrefGroups.filterShortcuts(); } @Override public void onCreate(Bundle savedInstanceState) { Alert.activity = this; super.onCreate(savedInstanceState); final Intent i = getIntent(); if(Intent.ACTION_CREATE_SHORTCUT.equals(i.getAction())) chooseShortcut(); else if(!A.isFull()) askDonate(); else if(!execShortcut(i)) finish(); } @Override public void onResume() { Alert.activity = this; super.onResume(); } @Override public void onPause() { super.onPause(); finish(); } private void chooseShortcut() { final Object[] shortcuts = getShortcuts(); final int r = SHORTCUT_ROW; final int n = shortcuts.length / r; final int[] items = new int[n]; for(int i=0; i<n; i++) items[i] = (Integer)shortcuts[i * r]; Alert.choose(A.s(R.string.app_shortcut), items, new Alert.Click(){ public void on(){ if(!A.isFull()) { askDonate(); return; } final int k = which * r; createShortcut(A.s(items[which]), (Integer)shortcuts[k+1], (String)shortcuts[k+2], (String)shortcuts[k+3], null); }}).setOnDismissListener(this); } private void createShortcut(String name, int icon, String extra, String extra2, String extra3) { if(icon == 0) { skipQuit = true; if( EXTRA_OPTION.equals(extra)) createOptionShortcut(); else if(EXTRA_FILTER.equals(extra)) createFilterShortcut(); else skipQuit = false; return; } Intent si = new Intent(Intent.ACTION_MAIN); si.setClassName(this, getClass().getName()); if(extra != null) si.putExtra(EXTRA_KEY , extra ); if(extra2 != null) si.putExtra(EXTRA_KEY2, extra2); if(extra3 != null) si.putExtra(EXTRA_KEY3, extra3); Intent i = new Intent(); i.putExtra(Intent.EXTRA_SHORTCUT_INTENT , si); i.putExtra(Intent.EXTRA_SHORTCUT_NAME , SHORTCUT_PREFIX + name); i.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(this, icon)); setResult(RESULT_OK, i); finish(); } private void createFilterShortcut() { final Object[] filters = getFilterShortcuts(); final int r = SHORTCUT_FILTER_ROW; final int n = filters.length / r; final int[] items = new int[n]; for(int i=0; i<n; i++) items[i] = (Integer)filters[i * r]; final String cat = A.s(R.string.filter_cat); Alert.choose(cat, items, new Alert.Click(){ public void on(){ final int k = which * r; createShortcut(cat, (Integer)filters[k+1], EXTRA_FILTER, (String)filters[k+2], null); }}).setOnDismissListener(this); } private void createOptionShortcut() { final String[][] sects = PrefGroups.sections(); final Object[] shortcuts = getShortcuts(); final int ns = shortcuts.length; int n = 0; for(String[] s : sects) n += s.length - 1; final Vector<String > items = new Vector<String >(n); final Vector<String > keys = new Vector<String >(n); final Vector<Integer> icons = new Vector<Integer>(n); for(String[] s : sects) { int h = 0, ic = 0; try { h = A.rstring(s[0]); for(int i=0; i<ns; i+=SHORTCUT_ROW) // look for shortcut icon if(h == (Integer)shortcuts[i]) { ic = (Integer)shortcuts[i + 1]; break; } } catch(Exception e) {} if(ic == 0) continue; String pref = "[ " + A.s(h) + " ]\n"; final int o = s.length; for(int t=0, i=1; i<o; i++, t=0) { final String k = s[i]; try { t = A.rstring(k+"_title"); } catch(Exception e) { try { if(k.startsWith("filter_enable_")) t = A.rstring(k.substring(k.lastIndexOf('_')+1) + "_enable_title"); } catch(Exception e2) {}} if(t == 0) continue; keys .add(k); items.add(pref + A.s(t)); icons.add(ic); if(pref.length() > 0) pref = ""; } } Alert.choose(A.s(R.string.app_shortcut), (String[])items.toArray(new String[items.size()]), new Alert.Click(){ public void on(){ String name = items.get(which); final int p = name.indexOf('\n'); if(p > 0) name = name.substring(p + 1).trim(); createShortcut(name, icons.get(which), EXTRA_OPTION, keys.get(which), name); }}).setOnDismissListener(this); } private boolean execShortcut(Intent i) { final String e = i.getStringExtra(EXTRA_KEY); final String e2 = i.getStringExtra(EXTRA_KEY2); if(EXTRA_REC .equals(e)) return execRecSrv(); if(EXTRA_PRF .equals(e)) return execProfiles(e2); if(EXTRA_ALARMER.equals(e)) return execAlarmer(e2); if(EXTRA_SCREEN .equals(e)) return execScreen(e2); if(EXTRA_FILTER .equals(e)) return execFilter(e2); if(EXTRA_OPTION .equals(e)) return execOption(e2, i.getStringExtra(EXTRA_KEY3)); A.toast(R.string.err); return false; } private boolean execAlarmer(String action) { ModeActivity.start(action, true); return false; } private boolean execProfiles(String prf) { if(prf != null) return restoreProfile(prf); if(profileChooser()) return true; A.toast(A.name()+": "+A.s(R.string.msg_prf_empty)); return false; } private boolean execRecSrv() { if(!RecService.isRunning()) A.toast(R.string.msg_rec_no); else { if(RecService.isRecord()) { RecService.recStop (0); A.toast(R.string.msg_rec_limit); } else { RecService.recStart(0); A.toast(R.string.msg_rec_go ); } try { Dev.iTel().showCallScreen(); } catch(Exception e) {} } return false; } private boolean execScreen(String clsName) { try { Intent i = new Intent(A.app(), Class.forName(clsName)); i.putExtra(EXTRA_KEY, 1); // inform the destination screen that it was launched through shortcut startActivity(i); } catch(Exception e) { A.toast(R.string.err); } return false; } private boolean execFilter(String sect) { try { if("blocksms".equals(sect) && !A.is(K.BLOCK_SMS_FILTER)) sect = "block"; String title = null; try { title = A.s(A.rstring(sect+"_cat")); } catch(Exception e) {} Intent i = new Intent(A.app(), FilterActivity.class); i.putExtra(EXTRA_KEY, 1); // inform the destination screen that it was launched through shortcut i.putExtra(FilterActivity.EXTRA_SECT , sect ); i.putExtra(FilterActivity.EXTRA_TITLE, title); FilterActivity.pref = null; startActivity(i); } catch(Exception e) { A.toast(R.string.err); } return false; } private boolean execOption(final String key, final String name) { skipQuit = false; if(K.PWD.equals(key)) return execChoosePwd(); if(execChangeEdit(key, name)) return true; String[] items; Object[] vals; int selected = -1; final Map<String,Pair<Integer,Integer>> mapInt = PrefGroups.intLabVals(); final Pair<Integer,Integer> pair = mapInt.get(key); if(pair != null) { Object arr[]; items = A.resources().getStringArray(pair.first ); arr = A.resources().getStringArray(pair.second); vals = new Integer[arr.length]; Object vsel; try { vsel = A.geti(key); } catch(Exception e) { vsel = A.gets(key); } final int n = arr.length; for(int i=0; i<n; i++) { Object v = arr[i]; vals[i] = v = Integer.parseInt((String)v); if(vsel.equals(v)) selected = i; } } else { final Object v = P.getDefaults().get(key); if(v instanceof Boolean) { items = new String[]{ A.s(R.string.inactive), A.s(R.string.active) }; vals = new Boolean[]{ false, true }; selected = A.is(key) ? 1 : 0; } else if(v instanceof Integer && key.indexOf("vol")>=0) { final int valsel = A.geti(key); CharSequence[][] arr = VolumeActivity.getVolumeLevels(AudioManager.STREAM_VOICE_CALL); CharSequence[] a0 = arr[0]; CharSequence[] a1 = arr[1]; final int n = a0.length; items = new String[n]; vals = new Integer[n]; for(int i=0; i<n; i++) { final int vol = Integer.parseInt(a1[i].toString()); items[i] = a0[i].toString(); vals [i] = vol; if(valsel == vol) selected = i; } } else { A.toast(R.string.err); return false; } } if(selected >= 0) items[selected] = ">> "+items[selected]+" <<"; final String[] items2 = items; final Object[] vals2 = vals; Alert.choose(name, items, new Alert.Click(){ public void on(){ final Object v = vals2[which]; if(A.has(K.PRF_NAME)) A.del(K.PRF_NAME); //if(mapInt.get(key) != null) A.put(key+K.WS, ((Integer)v).toString()); A.putc(key, v); optionSet(name, items2[which]); }}).setOnDismissListener(this); return true; } private boolean execChangeEdit(final String key, final String name) { for(String edit : PrefGroups.edits()) { if(!edit.equals(key)) continue; Alert.edit( name, A.gets(key), new Alert.Edited(){ public void on(String val){ if(A.has(K.PRF_NAME)) A.del(K.PRF_NAME); A.putc(key, val); optionSet(name, val); finish(); }}, new Alert.Edited(){ public void on(String val){ finish(); }} ); return true; } return false; } private boolean execChoosePwd() { Alert.pwdChoose(A.gets(K.PWD), new Alert.Edited() { @Override public void on(String pwd){ A.putc(K.PWD, pwd); } }).setOnDismissListener(this); return true; } private void optionSet(String name, String value) { A.toast(String.format(A.s(R.string.msg_option_set), name, value)); } private boolean profileChooser() { final String[] profiles = profiles(); if(profiles == null) return false; Alert.choose(A.s(R.string.profile_shortcut), profiles, new Alert.Click(){ @Override public void on() { restoreProfile(profiles[which]); } }).setOnDismissListener(this); return true; } private boolean restoreProfile(String name) { boolean res = P.restore(A.sdcardDir()+'/'+name+Conf.PRF_EXT); A.toast(String.format(A.s(res? R.string.msg_prf_restore_ok : R.string.msg_prf_restore_err), name)); return false; } private String[] profiles() { final String dir = A.sdcardDir(); if(dir == null) return null; String[] files = new File(dir).list(this); final int n = files.length; if(n <= 0) return null; final int l = Conf.PRF_EXT.length(); String[] profiles = new String[n]; for(int i=0; i<n; i++) profiles[i] = files[i].substring(0, files[i].length()-l); Arrays.sort(profiles, 0, profiles.length); return profiles; } private void askDonate() { skipQuit = true; Alert.msg( A.rawstr(R.raw.shortcut_free), new Alert.Click(){ public void on(){ Goto.marketDetails(License.FULL_PKG); }}, new Alert.Click(){ public void on(){ skipQuit = false; finish(); }} ).setOnDismissListener(this); } @Override public void onDismiss(DialogInterface dlg) { if(skipQuit) skipQuit = false; else finish(); } @Override public boolean accept(File dir, String fn) { return fn.endsWith(Conf.PRF_EXT); } }