package com.android.launcher;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import com.android.launcher.ExtendedDrawerSettings.ExtendedDrawerDBHelper;
public class SubMenuSettings extends ListActivity {
LayoutInflater mInflater;
Cursor mCursor;
SQLiteDatabase mDatabase;
ApplicationsAdapter mAdapter;
ListView mListView;
private static Cursor mCursorSubMenus;
public static Launcher activeLauncher;
public static final int mnuMoveItem = Menu.FIRST + 1;
private static ProgressDialog dlg;
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
menu.add("Manage submenus");
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
if(item.getTitle().equals("Manage submenus"))
{
Intent intent = new Intent(this, SubMenuManageMenusSettings.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onContextItemSelected(MenuItem item)
{
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
int itemId = Integer.valueOf(String.valueOf(info.position));
mCursor.moveToPosition(itemId);
int ApplicationId = mCursor.getInt(0);
String name = mCursor.getString(mCursor.getColumnIndex("name"));
String intent = mCursor.getString(mCursor.getColumnIndex("intent"));
refreshMenuList(mDatabase);
int i = 1;
while(mCursorSubMenus.moveToNext())
{
if(item.getItemId() == mnuMoveItem)
{
MoveApplication("MainMenu", name, intent, false);
break;
}
else if(item.getItemId() == mnuMoveItem+i)
{
MoveApplication(mCursorSubMenus.getString(mCursorSubMenus.getColumnIndex("name")), name, intent, false);
break;
}
i++;
}
return super.onContextItemSelected(item);
}
protected static class SubMenuDBHelper extends SQLiteOpenHelper {
private Context context;
public SubMenuDBHelper(Context context, boolean check) {
super(context, "submenu.sqlite", null, 2);
this.context = context;
if(check)
{
SQLiteDatabase db = this.getWritableDatabase();
Cursor data = db.query("submenus_entries", new String[] {"_id", "name", "intent", "submenu"}, null, null, "Upper(name)", null, null);
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager manager = context.getPackageManager();
final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
Log.d("SubMenuSettings", "Checking db...");
while(data.moveToNext())
{
boolean isInstalled = false;
for(int i = 0; i < apps.size(); i++)
{
ResolveInfo info = apps.get(i);
String apptitle = info.loadLabel(manager).toString();
if (apptitle == null) {
apptitle = info.activityInfo.name;
}
if(!apptitle.equals(data.getString(data.getColumnIndex("name"))))
continue;
ComponentName componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
ApplicationInfo application = new ApplicationInfo();
application.container = ItemInfo.NO_ID;
updateApplicationInfoTitleAndIcon(manager, info, application, context);
application.setActivity(componentName,
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
if(application.title.equals(data.getString(data.getColumnIndex("name"))))
{
isInstalled = true;
break;
}
}
if(!isInstalled)
{
db.delete("submenus_entries", "intent='"+data.getString(data.getColumnIndex("intent"))+"'", null);
}
}
Log.d("SubMenuSettings", "DB check successfull");
data.close();
db.close();
}
Log.d("SubMenuDBHelper", "Created");
}
@Override
public void onCreate(SQLiteDatabase db) {
String ddlScripts = "create table submenus_entries (_id integer primary key, name text, intent text, submenu text);";
db.execSQL(ddlScripts);
ddlScripts = "create table submenus (_id integer primary key, name text);";
db.execSQL(ddlScripts);
ContentValues values = new ContentValues();
values.put("name", "MainMenu");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Cursor data = db.query("submenus_entries", new String[] {"_id", "name", "intent", "submenu"}, null, null, "Upper(name)", null, null);
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager manager = context.getPackageManager();
final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
Log.d("SubMenuSettings", "Upgrading db to version 2...");
while(data.moveToNext())
{
for(int i = 0; i < apps.size(); i++)
{
ResolveInfo info = apps.get(i);
String apptitle = info.loadLabel(manager).toString();
if (apptitle == null) {
apptitle = info.activityInfo.name;
}
if(!apptitle.equals(data.getString(data.getColumnIndex("name"))))
continue;
ComponentName componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
ApplicationInfo application = new ApplicationInfo();
application.container = ItemInfo.NO_ID;
updateApplicationInfoTitleAndIcon(manager, info, application, context);
application.setActivity(componentName,
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
if(application.title.equals(data.getString(data.getColumnIndex("name"))))
{
int submenu = data.getColumnIndex("submenu");
int name = data.getColumnIndex("name");
ContentValues values = new ContentValues();
values.put("name", data.getString(name));
values.put("intent", application.intent.toURI());
values.put("submenu", data.getString(submenu));
if(db.update("submenus_entries", values, "name = '"+data.getString(name)+"'", null) <= 0)
{
Log.d("MoveApplication", "update <= 0");
}
else
Log.d("MoveApplication", "App "+data.getString(name)+" updated");
break;
}
}
}
Log.d("SubMenuSettings", "Upgrading successfull");
data.close();
}
@Override
public void onOpen(SQLiteDatabase db) {
Log.d("SubMenuDBHelper", "onOpen()");
}
}
public class ApplicationsAdapter extends CursorAdapter {
public ApplicationsAdapter(Context context, Cursor c) {
super(context, c);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView ApplicationNameText = (TextView) view.findViewById(R.id.txtTitle);
String applicationName = cursor.getString(1)+"\n"+cursor.getString(3);
PackageManager manager = SubMenuSettings.this.getPackageManager();
List<ResolveInfo> apps = null;
try {
apps = manager.queryIntentActivities(Intent.getIntent(cursor.getString(cursor.getColumnIndex("intent"))), 0);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ApplicationInfo application = new ApplicationInfo();
for(int i = 0; i < apps.size(); i++)
{
ResolveInfo info = apps.get(i);
ComponentName componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
application = new ApplicationInfo();
application.container = ItemInfo.NO_ID;
SubMenuSettings.updateApplicationInfoTitleAndIcon(manager, info, application, SubMenuSettings.this);
}
ApplicationNameText.setText(applicationName);
ApplicationNameText.setCompoundDrawablesWithIntrinsicBounds(application.icon, null, null, null);
ApplicationNameText.setTextSize(14);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = mInflater.inflate(R.layout.extended_drawersettings_row, null);
bindView(view, context, cursor);
return view;
}
}
private int mScrollX;
private int mScrollY;
private void refreshCursor() {
dlg.setTitle("Refreshing database cursor...");
dlg.setMessage("Please wait...");
mScrollX = 0;
mScrollY = 0;
try {
if(mCursor != null)
mCursor.close();
mCursor = mDatabase.query(false, "submenus_entries", new String[] { "_id", "name", "intent", "submenu" }, null, null, null, null, "Upper(submenu)", null);
if(mAdapter == null)
{
mAdapter = new ApplicationsAdapter(this, mCursor);
setListAdapter(mAdapter);
}
else
((ApplicationsAdapter)this.getListAdapter()).changeCursor(mCursor);
} catch(SQLiteException e) {
Log.d("SubMenuSettings", "Error: "+e.getMessage());
}
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.submenu_settings);
mListView = (ListView) findViewById(android.R.id.list);
mInflater = getLayoutInflater();
mListView.setOnCreateContextMenuListener(
new OnCreateContextMenuListener()
{
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
refreshMenuList(mDatabase);
menu.add(0, mnuMoveItem, 0, "Add to main menu");
int i = 1;
while(mCursorSubMenus.moveToNext())
{
menu.add(0, mnuMoveItem+i, 0, "Add to submenu "+mCursorSubMenus.getString(mCursorSubMenus.getColumnIndex("name")));
i++;
}
}
}
);
}
@Override
public void onResume()
{
super.onResume();
dlg = ProgressDialog.show(this, "Loading apps data", "");
SubMenuDBHelper hlp = new SubMenuDBHelper(this, true);
mDatabase = hlp.getWritableDatabase();
Log.d("SubMenuSettings", "Loaded db "+mDatabase.getPath());
InsertAllApps();
refreshCursor();
refreshMenuList(mDatabase);
dlg.cancel();
}
@Override
public void onDestroy()
{
super.onDestroy();
mCursorSubMenus.close();
mDatabase.close();
}
@Override
public void onStop()
{
super.onStop();
final LauncherModel model = Launcher.getModel();
model.loadApplications(false, activeLauncher, false);
}
public static void refreshMenuList(SQLiteDatabase db)
{
dlg.setTitle("Refreshing menu list...");
dlg.setMessage("Please wait...");
if(mCursorSubMenus != null)
mCursorSubMenus.close();
if(db != null)
mCursorSubMenus = db.query(false, "submenus", new String[] { "_id", "name" }, null, null, null, null, "Upper(name)", null);
}
void MoveApplication(String menu, String name, String intent, boolean insert)
{
SubMenuSettings.MoveApplication(mDatabase, menu, name, intent, insert);
refreshCursor();
}
public static void MoveApplication(SQLiteDatabase db, String menu, String name, String intent, boolean insert)
{
if(insert)
{
Cursor tmp = db.query(false, "submenus_entries", new String[] { "_id", "name", "intent" }, "intent = '"+intent+"'", null, null, null, null, null);
while(tmp.moveToNext())
{
tmp.close();
return;
}
tmp.close();
}
else
{
Cursor tmp = db.query(false, "submenus_entries", new String[] { "_id", "name", "intent" }, "intent = '"+intent+"'", null, null, null, null, null);
if(tmp.getCount() <= 0)
insert = true;
tmp.close();
}
Log.d("MoveApplication", "Starting move of "+name);
try {
ContentValues values = new ContentValues();
if(name != null)
values.put("name", name);
if(intent != null)
values.put("intent", intent);
if(menu != null)
values.put("submenu", menu);
if(insert)
{
db.insert("submenus_entries", null, values);
}
else
{
if(intent != null)
{
if(db.update("submenus_entries", values, "intent = '"+intent+"' AND name = "+DatabaseUtils.sqlEscapeString(name), null) <= 0)
{
Log.d("MoveApplication", "update <= 0");
}
else
Log.d("MoveApplication", "Submenu of app "+name+" updated");
}
else if(name != null)
{
if(db.update("submenus_entries", values, "name = '"+name+"'", null) <= 0)
{
Log.d("MoveApplication", "update <= 0");
}
else
Log.d("MoveApplication", "Submenu of app "+name+" updated");
}
}
}catch(SQLiteException e) {
Log.d("SubMenuSettings", "Error: "+e.getMessage());
}
}
void AddMenu(String title)
{
AddMenu(mDatabase, title);
refreshCursor();
}
void InsertAllApps()
{
dlg.setTitle("Checking for unknown apps...");
dlg.setMessage("Please wait...");
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager manager = this.getPackageManager();
final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
for(int i = 0; i < apps.size(); i++)
{
ResolveInfo info = apps.get(i);
ComponentName componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
ApplicationInfo application = new ApplicationInfo();
application.container = ItemInfo.NO_ID;
updateApplicationInfoTitleAndIcon(manager, info, application, this);
application.setActivity(componentName,
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
dlg.setMessage(application.title.toString());
MoveApplication("MainMenu", application.title.toString(), application.intent.toURI(), true);
}
}
public static ArrayList<ApplicationInfo> getSubmenuContents(Context context, String submenu)
{
ArrayList<ApplicationInfo> ret = new ArrayList<ApplicationInfo>();
SubMenuDBHelper hlp = new SubMenuDBHelper(context, false);
SQLiteDatabase db = hlp.getReadableDatabase();
Cursor data = db.query("submenus_entries", new String[] {"_id", "name", "intent", "submenu"}, "submenu = '"+submenu+"'", null, null, null, null);
PackageManager manager = context.getPackageManager();
while(data.moveToNext())
{
Intent intent;
try {
intent = Intent.getIntent(data.getString(2));
if(intent.resolveActivity(manager) == null)
{
continue;
}
} catch (URISyntaxException e) {
Log.d("SubMenuAdapter", "Could not get intent from uri!");
continue;
}
final List<ResolveInfo> apps = manager.queryIntentActivities(intent, 0);
if(apps.size() <= 0)
continue;
ResolveInfo info = apps.get(0);
String apptitle = info.loadLabel(manager).toString();
if (apptitle == null) {
apptitle = info.activityInfo.name;
}
ComponentName componentName = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
ApplicationInfo application = new ApplicationInfo();
application.container = ItemInfo.NO_ID;
updateApplicationInfoTitleAndIcon(manager, info, application, context);
application.setActivity(componentName,
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
ret.add(application);
}
data.close();
db.close();
return ret;
}
private static void updateApplicationInfoTitleAndIcon(PackageManager manager, ResolveInfo info,
ApplicationInfo application, Context context) {
application.title = info.loadLabel(manager);
if (application.title == null) {
application.title = info.activityInfo.name;
}
application.icon =
Utilities.createIconThumbnail(info.activityInfo.loadIcon(manager), context);
application.filtered = false;
}
public static void AddMenu(SQLiteDatabase db, String title)
{
ContentValues values = new ContentValues();
values.put("name", title);
db.insert("submenus", null, values);
}
public static void RenameMenu(SQLiteDatabase db, String which, String title)
{
ContentValues content_values = new ContentValues();
content_values.put("submenu", title);
ContentValues menu_values = new ContentValues();
menu_values.put("name", title);
db.update("submenus_entries", content_values, "submenu = '"+which+"'", null);
db.update("submenus", menu_values, "name = '"+which+"'", null);
}
public static void DeleteMenu(SQLiteDatabase db, String title)
{
ContentValues values = new ContentValues();
values.put("submenu", "MainMenu");
db.update("submenus_entries", values, "submenu = '"+title+"'", null);
db.delete("submenus", "name = '"+title+"'", null);
}
private static FileWriter openSDCardFileW(String fileName)
{
try {
File root = new File("sdcard/" + "Launcher");
if(root.exists() || root.mkdir())
{
File file = new File(root, fileName);
if(!file.exists())
file.createNewFile();
FileWriter writer;
writer = new FileWriter(file);
return writer;
}
} catch (IOException e) {
Log.d("BackupCreation", e.getMessage());
return null;
}
return null;
}
private static FileReader openSDCardFileR(String fileName)
{
try {
File root = new File("sdcard/" + "Launcher");
if(root.exists() || root.mkdir())
{
File file = new File(root, fileName);
if(!file.exists())
file.createNewFile();
FileReader reader;
reader = new FileReader(file);
return reader;
}
} catch (IOException e) {
Log.d("BackupCreation", e.getMessage());
return null;
}
return null;
}
public static boolean createConfigBackup(Context context)
{
String dbPath = "/data/data/com.android.launcher/databases/";
String prefPath = "/data/data/com.android.launcher/shared_prefs/";
String outPath = "/sdcard/Launcher/";
String submenuFile = dbPath+"/submenu.sqlite";
String extendedFile = dbPath+"/extendeddrawer.sqlite";
String prefsFile = prefPath+"/extendedlauncher.xml";
String submenuOutFile = "submenu.sql";
String extendedOutFile = "extendeddrawer.sql";
String prefsOutFile = "extendedlauncher.xml";
CommandHandler bkupSubmenu = new CommandHandler(true, "sqlite3 "+submenuFile+" .dump");
CommandHandler bkupExtended = new CommandHandler(true, "sqlite3 "+extendedFile+" .dump");
CommandHandler bkupPrefs = new CommandHandler(true, "cp "+prefsFile+" "+outPath+prefsOutFile);
bkupSubmenu.start();
bkupExtended.start();
bkupPrefs.start();
try {
bkupSubmenu.join();
bkupExtended.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
return false;
}
try {
FileWriter fw = openSDCardFileW(submenuOutFile);
if(fw == null)
return false;
ArrayList<String> lines = bkupSubmenu.getStdOutLines();
if(lines.size() > 0)
{
for(String line: lines)
{
fw.write(line);
fw.write("\n");
}
}
fw.flush();
fw.close();
fw = openSDCardFileW(extendedOutFile);
if(fw == null)
return false;
lines = bkupExtended.getStdOutLines();
if(lines.size() > 0)
{
for(String line: lines)
{
fw.write(line);
fw.write("\n");
}
}
fw.flush();
fw.close();
} catch (FileNotFoundException e) {
Log.d("BackupCreation", e.getMessage());
return false;
} catch (IOException e) {
Log.d("BackupCreation", e.getMessage());
return false;
}
return true;
}
public static boolean restoreConfigBackup(Context context)
{
String dbPath = "/data/data/com.android.launcher/databases/";
String prefPath = "/data/data/com.android.launcher/shared_prefs/";
String outPath = "/sdcard/Launcher/";
String submenuFile = dbPath+"/submenu.sqlite";
String extendedFile = dbPath+"/extendeddrawer.sqlite";
String prefsFile = prefPath+"/extendedlauncher.xml";
String submenuOutFile = "submenu.sql";
String extendedOutFile = "extendeddrawer.sql";
String prefsOutFile = "extendedlauncher.xml";
File root = new File("sdcard/" + "Launcher");
File bla = new File(root, submenuOutFile);
if(!bla.exists())
return false;
bla = new File(root, extendedOutFile);
if(!bla.exists())
return false;
CommandHandler bkupPrefs = new CommandHandler(true, "cp "+outPath+prefsOutFile+" "+prefsFile);
bkupPrefs.start();
CommandHandler rmSubmenuDB = new CommandHandler(true, "rm "+submenuFile);
CommandHandler rmExtendedDB = new CommandHandler(true, "rm "+extendedFile);
CommandHandler readSubmenuDB = new CommandHandler(true, "sqlite3 "+submenuFile+" \".read "+outPath+submenuOutFile+"\"");
CommandHandler readExtendedDB = new CommandHandler(true, "sqlite3 "+extendedFile+" \".read "+outPath+extendedOutFile+"\"");
rmSubmenuDB.start();
rmExtendedDB.start();
try {
rmSubmenuDB.join();
rmExtendedDB.join();
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
SubMenuDBHelper hlp = new SubMenuDBHelper(context, false);
hlp.getWritableDatabase();
hlp.close();
ExtendedDrawerDBHelper extendedHlp = new ExtendedDrawerDBHelper(context);
extendedHlp.getWritableDatabase();
extendedHlp.close();
readSubmenuDB.start();
readExtendedDB.start();
return true;
}
//From wifi teether for root users
static class CommandHandler extends Thread {
public static final String MSG_TAG = "SubMenu -> ExecuteProcess";
private Process process = null;
private String command;
private Runtime runtime;
private ArrayList<String> stdOutLines;
private int exitCode = -1;
private boolean runAsRoot = false;
CommandHandler(String command) {
this.command = command;
this.runAsRoot = false;
this.runtime = Runtime.getRuntime();
}
CommandHandler(boolean runAsRoot, String command) {
this.command = command;
this.runAsRoot = runAsRoot;
this.runtime = Runtime.getRuntime();
}
public int getExitCode() {
return this.exitCode;
}
public ArrayList<String> getStdOutLines() {
return this.stdOutLines;
}
public void destroy() {
try {
if (this.process != null) {
this.process.destroy();
}
this.interrupt();
}
catch (Exception ex) {
// nothing
}
}
public void run() {
DataOutputStream os = null;
InputStream stderr = null;
InputStream stdout = null;
String line;
this.stdOutLines = new ArrayList<String>();
Log.d(MSG_TAG, "Executing command (root:"+this.runAsRoot+"): " + command);
try {
this.runtime.gc();
if (this.runAsRoot) {
this.process = this.runtime.exec("su");
}
else {
this.process = this.runtime.exec(command);
}
stderr = this.process.getErrorStream();
stdout = this.process.getInputStream();
BufferedReader errBr = new BufferedReader(new InputStreamReader(stderr), 8192);
BufferedReader inputBr = new BufferedReader(new InputStreamReader(stdout), 8192);
if (this.runAsRoot) {
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(command+"\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
}
while ((line = inputBr.readLine()) != null) {
stdOutLines.add(line.trim());
Log.d(MSG_TAG, "STDOUT: "+line.trim());
}
while ((line = errBr.readLine()) != null);
this.exitCode = this.process.waitFor();
} catch (Exception e) {
Log.d(MSG_TAG, "Unexpected error - Here is what I know: "+e.getMessage());
}
finally {
// Closing streams
try {
if (os != null)
os.close();
if (stderr != null)
stderr.close();
if (stdout != null)
stdout.close();
} catch (Exception ex) {;}
// Destroy process
try {
this.process.destroy();
} catch (Exception e) {;}
}
}
}
}