diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ee7a3267e..f9782bf9d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -14,6 +14,7 @@ + diff --git a/res/values/array.xml b/res/values/array.xml new file mode 100644 index 000000000..758da0f35 --- /dev/null +++ b/res/values/array.xml @@ -0,0 +1,19 @@ + + + + Never + Hourly + Every 4 Hours + Every 12 Hours + Daily + + + + 0 + 1 + 4 + 12 + 24 + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index c670e283c..8455cc4e5 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,32 +1,36 @@ - FDroid + FDroid About FDroid - Based on Aptoide.\nReleased under the GNU GPL v2 license. + Based on Aptoide.\nReleased under the GNU GPL v2 + license. Home: e-Mail: Web Site - - You have no repositories configured!\n\nA repository is a source of applications. To add one, press the MENU button now and enter the URL.\n\nA repository URL looks something like this: http://f-droid.org/repo + + You have no repositories configured!\n\nA + repository is a source of applications. To add one, press the MENU + button now and enter the URL.\n\nA repository URL looks something like + this: http://f-droid.org/repo Not Installed - + Update possible - Ver.: - + Ok Yes No Add new repository Add - + Cancel Choose repository to remove - + Could not connect to server! - + Update repositories Installed Available @@ -39,8 +43,6 @@ Could not connect to server! Download Getting application from - - @@ -50,45 +52,48 @@ -Repository URL - - - Installed: - - Install - Uninstall - Update! - - There updates available for some installed applications.\nDo you wish to see them? - The list of repositories in use has been changed.\nDo you wish to update them? - - Could not connect to server or apk file is corrupt! - Getting application from:\n - Update - Manage Repos - - - About - - - - New Repository - Remove Repository - - - -Install -Uninstall -Web Site -Issues -Source Code -Market -Update + Repository URL + + + + Installed: + + Install + Uninstall + Update! + + There updates available for some installed + applications.\nDo you wish to see them? + The list of repositories in use has been + changed.\nDo you wish to update them? + + Could not connect to server or apk file is corrupt! + + Getting application from:\n + + Update + Manage Repos + Preferences + About + New Repository + Remove Repository + + + + Install + Uninstall + Web Site + Issues + Source Code + Market + Update + + Version %s installed + Not installed (%d available) + Installed + Downloaded file is corrupt + -Version %s installed -Not installed (%d available) -Installed -Downloaded file is corrupt diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml new file mode 100644 index 000000000..e1dd3a6d1 --- /dev/null +++ b/res/xml/preferences.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/src/org/fdroid/fdroid/AppDetails.java b/src/org/fdroid/fdroid/AppDetails.java index 517343155..940855aff 100644 --- a/src/org/fdroid/fdroid/AppDetails.java +++ b/src/org/fdroid/fdroid/AppDetails.java @@ -36,6 +36,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.preference.PreferenceManager; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; @@ -46,6 +47,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -163,6 +165,18 @@ public class AppDetails extends ListActivity { } + private boolean pref_cacheDownloaded; + + @Override + protected void onStart() { + super.onStart(); + + // Get the preferences we're going to use in this Activity... + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(getBaseContext()); + pref_cacheDownloaded = prefs.getBoolean("cacheDownloaded", true); + } + // Reset the display and list contents. Used when entering the activity, and // also when something has been installed/uninstalled. In the latter case, // 'update' is true to make the installed status get refreshed. @@ -347,61 +361,99 @@ public class AppDetails extends ListActivity { public void run() { // Download the apk file from the repository... + File f; String apk_file = null; + String apkname = curapk.apkName; + String localfile = new String(LOCAL_PATH + "/" + apkname); try { - String apkname = curapk.apkName; - String localfile = new String(LOCAL_PATH + "/" + apkname); - String remotefile = curapk.server + "/" - + apkname.replace(" ", "%20"); + // See if we already have this apk cached... + f = new File(localfile); + if (f.exists()) { + // We do - if its hash matches, we'll use it... + Md5Handler hash = new Md5Handler(); + String calcedhash = hash.md5Calc(f); + if (curapk.hash.equalsIgnoreCase(calcedhash)) { + apk_file = localfile; + Log.d("FDroid", "Using cached apk at " + localfile); + Message msg = new Message(); + msg.arg1 = 0; + msg.arg2 = 1; + msg.obj = new String(localfile); + download_handler.sendMessage(msg); + msg=new Message(); + msg.arg1 = 1; + download_handler.sendMessage(msg); + } else { + Log.d("FDroid", "Not using cached apk at " + + localfile); + f.delete(); + } + } - Log.d("FDroid", "Downloading apk from " + remotefile); + // If we haven't got the apk locally, we'll have to download + // it... + if (apk_file == null) { - Message msg = new Message(); - msg.arg1 = 0; - msg.arg2 = curapk.size; - msg.obj = new String(remotefile); - download_handler.sendMessage(msg); + String remotefile = curapk.server + "/" + + apkname.replace(" ", "%20"); + Log.d("FDroid", "Downloading apk from " + remotefile); - BufferedInputStream getit = new BufferedInputStream( - new URL(remotefile).openStream(), 8192); - - FileOutputStream saveit = new FileOutputStream(localfile); - BufferedOutputStream bout = new BufferedOutputStream( - saveit, 1024); - byte data[] = new byte[1024]; - - int totalRead = 0; - int bytesRead = getit.read(data, 0, 1024); - while (bytesRead != -1) { - bout.write(data, 0, bytesRead); - totalRead += bytesRead; - msg = new Message(); - msg.arg1 = totalRead; + Message msg = new Message(); + msg.arg1 = 0; + msg.arg2 = curapk.size; + msg.obj = new String(remotefile); download_handler.sendMessage(msg); - bytesRead = getit.read(data, 0, 1024); - } - bout.close(); - getit.close(); - saveit.close(); - File f = new File(localfile); - Md5Handler hash = new Md5Handler(); - String calcedhash = hash.md5Calc(f); - if (curapk.hash.equalsIgnoreCase(calcedhash)) { - apk_file = localfile; - } else { - msg = new Message(); - msg.obj = getString(R.string.corrupt_download); - download_error_handler.sendMessage(msg); - Log.d("FDroid", "Downloaded file hash of " + calcedhash - + " did not match repo's " + curapk.hash); - } + BufferedInputStream getit = new BufferedInputStream( + new URL(remotefile).openStream(), 8192); + + FileOutputStream saveit = new FileOutputStream( + localfile); + BufferedOutputStream bout = new BufferedOutputStream( + saveit, 1024); + byte data[] = new byte[1024]; + + int totalRead = 0; + int bytesRead = getit.read(data, 0, 1024); + while (bytesRead != -1) { + bout.write(data, 0, bytesRead); + totalRead += bytesRead; + msg = new Message(); + msg.arg1 = totalRead; + download_handler.sendMessage(msg); + bytesRead = getit.read(data, 0, 1024); + } + bout.close(); + getit.close(); + saveit.close(); + f = new File(localfile); + Md5Handler hash = new Md5Handler(); + String calcedhash = hash.md5Calc(f); + if (curapk.hash.equalsIgnoreCase(calcedhash)) { + apk_file = localfile; + } else { + msg = new Message(); + msg.obj = getString(R.string.corrupt_download); + download_error_handler.sendMessage(msg); + Log.d("FDroid", "Downloaded file hash of " + + calcedhash + " did not match repo's " + + curapk.hash); + // No point keeping a bad file, whether we're + // caching or + // not. + f = new File(localfile); + f.delete(); + } + } } catch (Exception e) { Log.d("FDroid", "Download failed - " + e.getMessage()); Message msg = new Message(); msg.obj = e.getMessage(); download_error_handler.sendMessage(msg); + // Get rid of any partial download... + f = new File(localfile); + f.delete(); } if (apk_file != null) { @@ -445,6 +497,7 @@ public class AppDetails extends ListActivity { public void handleMessage(Message msg) { String apk_file = (String) msg.obj; installApk(apk_file); + pd.dismiss(); } }; @@ -462,21 +515,29 @@ public class AppDetails extends ListActivity { startActivityForResult(intent, REQUEST_UNINSTALL); } - private void installApk(String id) { + private void installApk(String file) { Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); - intent.setDataAndType(Uri.parse("file://" + id), + intent.setDataAndType(Uri.parse("file://" + file), "application/vnd.android.package-archive"); - Message msg = new Message(); - msg.arg1 = 1; - download_handler.sendMessage(msg); - startActivityForResult(intent, REQUEST_INSTALL); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if(requestCode==REQUEST_INSTALL) { + // If we're not meant to be caching, delete the apk file we just + // installed (or maybe the user cancelled the install - doesn't matter) + // from the SD card... + if (!pref_cacheDownloaded) { + String apkname = curapk.apkName; + String apk_file = new String(LOCAL_PATH + "/" + apkname); + File file = new File(apk_file); + file.delete(); + } + } + reset(true); } diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java index cb35e13e8..ff1fde03f 100644 --- a/src/org/fdroid/fdroid/FDroid.java +++ b/src/org/fdroid/fdroid/FDroid.java @@ -152,7 +152,8 @@ public class FDroid extends TabActivity implements OnItemClickListener { private static final int UPDATE_REPO = Menu.FIRST; private static final int MANAGE_REPO = Menu.FIRST + 1; private static final int RESET_DB = Menu.FIRST + 2; - private static final int ABOUT = Menu.FIRST + 3; + private static final int PREFERENCES = Menu.FIRST + 3; + private static final int ABOUT = Menu.FIRST + 4; private DB db = null; @@ -222,7 +223,9 @@ public class FDroid extends TabActivity implements OnItemClickListener { android.R.drawable.ic_menu_agenda); menu.add(Menu.NONE, RESET_DB, 3, "Reset DB").setIcon( android.R.drawable.ic_menu_revert); - menu.add(Menu.NONE, ABOUT, 4, R.string.menu_about).setIcon( + menu.add(Menu.NONE, PREFERENCES, 4, R.string.menu_preferences).setIcon( + android.R.drawable.ic_menu_preferences); + menu.add(Menu.NONE, ABOUT, 5, R.string.menu_about).setIcon( android.R.drawable.ic_menu_help); return true; } @@ -246,6 +249,11 @@ public class FDroid extends TabActivity implements OnItemClickListener { populateLists(true); return true; + case PREFERENCES: + Intent prefs = new Intent(getBaseContext(), Preferences.class); + startActivity(prefs); + return true; + case ABOUT: LayoutInflater li = LayoutInflater.from(this); View view = li.inflate(R.layout.about, null); diff --git a/src/org/fdroid/fdroid/Preferences.java b/src/org/fdroid/fdroid/Preferences.java new file mode 100644 index 000000000..cc24264cd --- /dev/null +++ b/src/org/fdroid/fdroid/Preferences.java @@ -0,0 +1,14 @@ +package org.fdroid.fdroid; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class Preferences extends PreferenceActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } + +}