Added preferences screen and implemented (optional) caching

This commit is contained in:
Ciaran Gultnieks 2010-11-07 23:06:46 +00:00
parent 37182c04b1
commit 53a9e0e796
7 changed files with 224 additions and 99 deletions

View File

@ -14,6 +14,7 @@
<activity android:name="ManageRepo" />
<activity android:name="Settings" />
<activity android:name="AppDetails" />
<activity android:name="Preferences" />
</application>
<uses-permission android:name="android.permission.INTERNET" />

19
res/values/array.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string-array name="updateIntervalNames">
<item>Never</item>
<item>Hourly</item>
<item>Every 4 Hours</item>
<item>Every 12 Hours</item>
<item>Daily</item>
</string-array>
<string-array name="updateIntervalValues">
<item>0</item>
<item>1</item>
<item>4</item>
<item>12</item>
<item>24</item>
</string-array>
</resources>

View File

@ -1,32 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">FDroid</string>
<string name="app_name">FDroid</string>
<string name="about_title">About FDroid</string>
<string name="about_desc">Based on Aptoide.\nReleased under the GNU GPL v2 license.</string>
<string name="about_desc">Based on Aptoide.\nReleased under the GNU GPL v2
license.</string>
<string name="about_site">Home: </string>
<string name="about_mail">e-Mail: </string>
<string name="about_website">Web Site</string>
<string name="no_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</string>
<string name="no_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</string>
<string name="not_inst">Not Installed</string>
<string name="installed_update">Update possible - Ver.:</string>
<string name="ok">Ok</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="repo_add_title">Add new repository</string>
<string name="repo_add_add">Add</string>
<string name="cancel">Cancel</string>
<string name="repo_delete_title">Choose repository to remove</string>
<string name="server_connection_error">Could not connect to server!</string>
<string name="repo_update_title">Update repositories</string>
<string name="tab_installed">Installed</string>
<string name="tab_noninstalled">Available</string>
@ -39,8 +43,6 @@
<string name="connection_error_msg">Could not connect to server!</string>
<string name="download">Download</string>
<string name="download_server">Getting application from</string>
@ -50,45 +52,48 @@
<string name="repo_add_url">Repository URL</string>
<string name="isinst">Installed: </string>
<string name="install">Install </string>
<string name="uninstall">Uninstall </string>
<string name="update">Update!</string>
<string name="update_alrt">There updates available for some installed applications.\nDo you wish to see them?</string>
<string name="repo_alrt">The list of repositories in use has been changed.\nDo you wish to update them?</string>
<string name="error_download_alrt">Could not connect to server or apk file is corrupt!</string>
<string name="download_alrt">Getting application from:\n </string>
<string name="menu_update_repo">Update</string>
<string name="menu_manage">Manage Repos</string>
<string name="menu_about">About</string>
<string name="menu_add_repo">New Repository</string>
<string name="menu_rem_repo">Remove Repository</string>
<string name="menu_install">Install</string>
<string name="menu_uninstall">Uninstall</string>
<string name="menu_website">Web Site</string>
<string name="menu_issues">Issues</string>
<string name="menu_source">Source Code</string>
<string name="menu_market">Market</string>
<string name="menu_update">Update</string>
<string name="repo_add_url">Repository URL</string>
<string name="isinst">Installed: </string>
<string name="install">Install </string>
<string name="uninstall">Uninstall </string>
<string name="update">Update!</string>
<string name="update_alrt">There updates available for some installed
applications.\nDo you wish to see them?</string>
<string name="repo_alrt">The list of repositories in use has been
changed.\nDo you wish to update them?</string>
<string name="error_download_alrt">Could not connect to server or apk file is corrupt!
</string>
<string name="download_alrt">Getting application from:\n </string>
<string name="menu_update_repo">Update</string>
<string name="menu_manage">Manage Repos</string>
<string name="menu_preferences">Preferences</string>
<string name="menu_about">About</string>
<string name="menu_add_repo">New Repository</string>
<string name="menu_rem_repo">Remove Repository</string>
<string name="menu_install">Install</string>
<string name="menu_uninstall">Uninstall</string>
<string name="menu_website">Web Site</string>
<string name="menu_issues">Issues</string>
<string name="menu_source">Source Code</string>
<string name="menu_market">Market</string>
<string name="menu_update">Update</string>
<string name="details_installed">Version %s installed</string>
<string name="details_notinstalled">Not installed (%d available)</string>
<string name="inst">Installed</string>
<string name="corrupt_download">Downloaded file is corrupt</string>
<string name="details_installed">Version %s installed</string>
<string name="details_notinstalled">Not installed (%d available)</string>
<string name="inst">Installed</string>
<string name="corrupt_download">Downloaded file is corrupt</string>
</resources>

17
res/xml/preferences.xml Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Storage">
<CheckBoxPreference android:title="Cache downloaded apps"
android:defaultValue="false" android:summary="Keep downloaded apk files on SD card"
android:key="cacheDownloaded" />
</PreferenceCategory>
<PreferenceCategory android:title="Updates">
<ListPreference android:title="Automatic repo scan"
android:summary="Update apps list from repositories automatically"
android:key="updateInterval" android:defaultValue="0"
android:entries="@array/updateIntervalNames" android:entryValues="@array/updateIntervalValues" />
<CheckBoxPreference android:title="Notify"
android:defaultValue="false" android:summary="Notify when new updates are available"
android:key="updateNotify" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
}