Tidied up some file-related stuff

This commit is contained in:
Ciaran Gultnieks 2012-09-14 09:24:08 +01:00
parent cd44c8b80b
commit 3c0ccf2f4f
7 changed files with 114 additions and 131 deletions

View File

@ -314,10 +314,9 @@ public class AppDetails extends ListActivity {
private void resetViews() { private void resetViews() {
// Set the icon... // Set the icon...
ImageView iv = (ImageView) findViewById(R.id.icon); ImageView iv = (ImageView) findViewById(R.id.icon);
String icon_path = DB.getIconsPath() + app.icon; File icon = new File(DB.getIconsPath(), app.icon);
File test_icon = new File(icon_path); if (icon.exists()) {
if (test_icon.exists()) { iv.setImageDrawable(new BitmapDrawable(icon.getPath()));
iv.setImageDrawable(new BitmapDrawable(icon_path));
} else { } else {
iv.setImageResource(android.R.drawable.sym_def_app_icon); iv.setImageResource(android.R.drawable.sym_def_app_icon);
} }
@ -473,10 +472,10 @@ public class AppDetails extends ListActivity {
} }
private void installApk(String file) { private void installApk(File file) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW); intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + file), intent.setDataAndType(Uri.parse("file://" + file.getPath()),
"application/vnd.android.package-archive"); "application/vnd.android.package-archive");
startActivityForResult(intent, REQUEST_INSTALL); startActivityForResult(intent, REQUEST_INSTALL);
((FDroidApp) getApplication()).invalidateApps(); ((FDroidApp) getApplication()).invalidateApps();
@ -509,7 +508,7 @@ public class AppDetails extends ListActivity {
private Downloader download; private Downloader download;
private ProgressDialog pd; private ProgressDialog pd;
private boolean updating; private boolean updating;
private String localFile; private File localFile;
public DownloadHandler(DB.Apk apk) { public DownloadHandler(DB.Apk apk) {
download = new Downloader(apk); download = new Downloader(apk);
@ -589,9 +588,8 @@ public class AppDetails extends ListActivity {
// installed (or maybe the user cancelled the install - doesn't // installed (or maybe the user cancelled the install - doesn't
// matter) from the SD card... // matter) from the SD card...
if (!pref_cacheDownloaded) { if (!pref_cacheDownloaded) {
File file = new File(localFile); Log.d("FDroid", "Cleaning up: " + localFile.getPath());
Log.d("FDroid", "Cleaning up: " + file); localFile.delete();
file.delete();
localFile = null; localFile = null;
} }
} }

View File

@ -82,11 +82,10 @@ public class AppListAdapter extends BaseAdapter {
summary.setText(app.summary); summary.setText(app.summary);
ImageView icon = (ImageView) v.findViewById(R.id.icon); ImageView icon = (ImageView) v.findViewById(R.id.icon);
String iconpath = new String(DB.getIconsPath() + app.icon); File icn = new File(DB.getIconsPath(), app.icon);
File icn = new File(iconpath);
if (icn.exists() && icn.length() > 0) { if (icn.exists() && icn.length() > 0) {
new Uri.Builder().build(); new Uri.Builder().build();
icon.setImageURI(Uri.parse(iconpath)); icon.setImageURI(Uri.parse(icn.getPath()));
} else { } else {
icon.setImageResource(android.R.drawable.sym_def_app_icon); icon.setImageResource(android.R.drawable.sym_def_app_icon);
} }

View File

@ -19,10 +19,10 @@
package org.fdroid.fdroid; package org.fdroid.fdroid;
import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -42,6 +42,7 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build; import android.os.Build;
import android.os.Environment;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils.SimpleStringSplitter; import android.text.TextUtils.SimpleStringSplitter;
import android.util.Log; import android.util.Log;
@ -419,8 +420,12 @@ public class DB {
} }
public static String getIconsPath() { public static File getDataPath() {
return "/sdcard/.fdroid/icons/"; return new File(Environment.getExternalStorageDirectory(), ".fdroid");
}
public static File getIconsPath() {
return new File(getDataPath(), "icons");
} }
private PackageManager mPm; private PackageManager mPm;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2010-2011 Ciaran Gultnieks <ciaran@ciarang.com> * Copyright (C) 2010-2012 Ciaran Gultnieks <ciaran@ciarang.com>
* Copyright (C) 2011 Henrik Tunedal <tunedal@gmail.com> * Copyright (C) 2011 Henrik Tunedal <tunedal@gmail.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -29,14 +29,17 @@ import java.net.URL;
public class Downloader extends Thread { public class Downloader extends Thread {
private static final String LOCAL_PATH = "/sdcard/.fdroid";
private DB.Apk curapk; private DB.Apk curapk;
private String filename; private String filename;
private String localfile; private File localfile;
public static enum Status { STARTING, RUNNING, ERROR, DONE, CANCELLED }; public static enum Status {
public static enum Error { CORRUPT, UNKNOWN }; STARTING, RUNNING, ERROR, DONE, CANCELLED
};
public static enum Error {
CORRUPT, UNKNOWN
};
private Status status = Status.STARTING; private Status status = Status.STARTING;
private Error error; private Error error;
@ -58,6 +61,7 @@ public class Downloader extends Thread {
public synchronized int getProgress() { public synchronized int getProgress() {
return progress; return progress;
} }
public synchronized int getMax() { public synchronized int getMax() {
return max; return max;
} }
@ -66,6 +70,7 @@ public class Downloader extends Thread {
public synchronized Error getErrorType() { public synchronized Error getErrorType() {
return error; return error;
} }
public synchronized String getErrorMessage() { public synchronized String getErrorMessage() {
return errorMessage; return errorMessage;
} }
@ -75,8 +80,8 @@ public class Downloader extends Thread {
return filename; return filename;
} }
// Path to the downloaded APK // The downloaded APK. Valid only when getStatus() has returned STATUS.DONE.
public synchronized String localFile() { public File localFile() {
return localfile; return localfile;
} }
@ -87,125 +92,103 @@ public class Downloader extends Thread {
public void run() { public void run() {
// Download the apk file from the repository...
File f;
String apk_file = null;
String apkname = curapk.apkName; String apkname = curapk.apkName;
synchronized (this) { localfile = new File(DB.getDataPath(), apkname);
localfile = new String(LOCAL_PATH + "/" + apkname);
}
try { try {
// See if we already have this apk cached... // See if we already have this apk cached...
f = new File(localfile); if (localfile.exists()) {
if (f.exists()) {
// We do - if its hash matches, we'll use it... // We do - if its hash matches, we'll use it...
Hasher hash = new Hasher(curapk.hashType, f); Hasher hash = new Hasher(curapk.hashType, localfile);
if (hash.match(curapk.hash)) { if (hash.match(curapk.hash)) {
Log.d("FDroid", "Using cached apk at " + localfile); Log.d("FDroid", "Using cached apk at " + localfile);
synchronized (this) { synchronized (this) {
filename = apk_file = localfile;
progress = 1; progress = 1;
max = 1; max = 1;
status = Status.RUNNING; status = Status.DONE;
return;
} }
} else { } else {
Log.d("FDroid", "Not using cached apk at " Log.d("FDroid", "Not using cached apk at " + localfile);
+ localfile); localfile.delete();
f.delete();
} }
} }
// If we haven't got the apk locally, we'll have to download // If we haven't got the apk locally, we'll have to download it...
// it... String remotefile;
if (apk_file == null) { if (curapk.apkSource == null) {
remotefile = curapk.server + "/" + apkname.replace(" ", "%20");
} else {
remotefile = curapk.apkSource;
}
Log.d("FDroid", "Downloading apk from " + remotefile);
synchronized (this) {
filename = remotefile;
progress = 0;
max = curapk.size;
status = Status.RUNNING;
}
String remotefile; BufferedInputStream getit = new BufferedInputStream(new URL(
if (curapk.apkSource == null) { remotefile).openStream(), 8192);
remotefile = curapk.server + "/"
+ apkname.replace(" ", "%20");
} else {
remotefile = curapk.apkSource;
}
Log.d("FDroid", "Downloading apk from " + remotefile);
synchronized (this) {
filename = remotefile;
progress = 0;
max = curapk.size;
status = Status.RUNNING;
}
BufferedInputStream getit = FileOutputStream saveit = new FileOutputStream(localfile);
new BufferedInputStream(new URL(remotefile).openStream(), BufferedOutputStream bout = new BufferedOutputStream(saveit, 1024);
8192); byte data[] = new byte[1024];
FileOutputStream saveit = int totalRead = 0;
new FileOutputStream(localfile); int bytesRead = getit.read(data, 0, 1024);
BufferedOutputStream bout = while (bytesRead != -1) {
new BufferedOutputStream(saveit, 1024);
byte data[] = new byte[1024];
int totalRead = 0;
int bytesRead = getit.read(data, 0, 1024);
while (bytesRead != -1) {
if (isInterrupted()) {
Log.d("FDroid", "Download cancelled!");
break;
}
bout.write(data, 0, bytesRead);
totalRead += bytesRead;
synchronized (this) {
progress = totalRead;
}
bytesRead = getit.read(data, 0, 1024);
}
bout.close();
getit.close();
saveit.close();
f = new File(localfile);
if (isInterrupted()) { if (isInterrupted()) {
f.delete(); Log.d("FDroid", "Download cancelled!");
synchronized (this) { break;
status = Status.CANCELLED;
}
return;
} }
Hasher hash = new Hasher(curapk.hashType, f); bout.write(data, 0, bytesRead);
if (hash.match(curapk.hash)) { totalRead += bytesRead;
apk_file = localfile; synchronized (this) {
} else { progress = totalRead;
synchronized (this) { }
error = Error.CORRUPT; bytesRead = getit.read(data, 0, 1024);
errorMessage = null; }
status = Status.ERROR; bout.close();
} getit.close();
Log.d("FDroid", "Downloaded file hash of " saveit.close();
+ hash.getHash() + " did not match repo's "
+ curapk.hash); if (isInterrupted()) {
localfile.delete();
synchronized (this) {
status = Status.CANCELLED;
}
return;
}
Hasher hash = new Hasher(curapk.hashType, localfile);
if (!hash.match(curapk.hash)) {
synchronized (this) {
Log.d("FDroid", "Downloaded file hash of " + hash.getHash()
+ " did not match repo's " + curapk.hash);
// No point keeping a bad file, whether we're // No point keeping a bad file, whether we're
// caching or not. // caching or not.
f = new File(localfile); localfile.delete();
f.delete(); error = Error.CORRUPT;
errorMessage = null;
status = Status.ERROR;
return;
} }
} }
} catch (Exception e) { } catch (Exception e) {
Log.e("FDroid", "Download failed:\n" Log.e("FDroid", "Download failed:\n" + Log.getStackTraceString(e));
+ Log.getStackTraceString(e));
synchronized (this) { synchronized (this) {
localfile.delete();
error = Error.UNKNOWN; error = Error.UNKNOWN;
errorMessage = e.toString(); errorMessage = e.toString();
status = Status.ERROR; status = Status.ERROR;
return;
} }
// Get rid of any partial download...
f = new File(localfile);
f.delete();
} }
if (apk_file != null) { Log.d("FDroid", "Download finished: " + localfile);
synchronized (this) { synchronized (this) {
status = Status.DONE; status = Status.DONE;
}
Log.d("FDroid", "Download finished: " + apk_file);
} }
} }
} }

View File

@ -19,7 +19,6 @@
package org.fdroid.fdroid; package org.fdroid.fdroid;
import java.io.File;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Vector; import java.util.Vector;
@ -33,14 +32,12 @@ import android.app.TabActivity;
import android.app.AlertDialog.Builder; import android.app.AlertDialog.Builder;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@ -60,8 +57,6 @@ import android.widget.TabHost.TabSpec;
public class FDroid extends TabActivity implements OnItemClickListener, public class FDroid extends TabActivity implements OnItemClickListener,
OnItemSelectedListener { OnItemSelectedListener {
private String LOCAL_PATH = "/sdcard/.fdroid";
private static final int REQUEST_APPDETAILS = 0; private static final int REQUEST_APPDETAILS = 0;
private static final int REQUEST_MANAGEREPOS = 1; private static final int REQUEST_MANAGEREPOS = 1;
private static final int REQUEST_PREFS = 2; private static final int REQUEST_PREFS = 2;
@ -109,14 +104,6 @@ public class FDroid extends TabActivity implements OnItemClickListener,
setContentView(R.layout.fdroid); setContentView(R.layout.fdroid);
File local_path = new File(LOCAL_PATH);
if (!local_path.exists())
local_path.mkdir();
File icon_path = new File(DB.getIconsPath());
if (!icon_path.exists())
icon_path.mkdir();
Spinner spinner = (Spinner) findViewById(R.id.category); Spinner spinner = (Spinner) findViewById(R.id.category);
categories = new ArrayAdapter<String>(this, categories = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, new Vector<String>()); android.R.layout.simple_spinner_item, new Vector<String>());

View File

@ -18,10 +18,12 @@
package org.fdroid.fdroid; package org.fdroid.fdroid;
import java.io.File;
import java.util.Vector; import java.util.Vector;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import android.app.Application; import android.app.Application;
import android.util.Log;
public class FDroidApp extends Application { public class FDroidApp extends Application {
@ -29,8 +31,19 @@ public class FDroidApp extends Application {
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
File local_path = DB.getDataPath();
Log.d("FDroid", "Data path is " + local_path.getPath());
if (!local_path.exists())
local_path.mkdir();
File icon_path = DB.getIconsPath();
Log.d("FDroid", "Icon path is " + icon_path.getPath());
if (!icon_path.exists())
icon_path.mkdir();
apps = null; apps = null;
DB.initDB(getApplicationContext()); DB.initDB(getApplicationContext());
} }
// Global list of all known applications. // Global list of all known applications.

View File

@ -242,8 +242,7 @@ public class RepoXMLHandler extends DefaultHandler {
private void getIcon(DB.App app) { private void getIcon(DB.App app) {
try { try {
String destpath = DB.getIconsPath() + app.icon; File f = new File(DB.getIconsPath(), app.icon);
File f = new File(destpath);
if (f.exists()) if (f.exists())
return; return;
@ -252,7 +251,7 @@ public class RepoXMLHandler extends DefaultHandler {
if (uc.getResponseCode() == 200) { if (uc.getResponseCode() == 200) {
BufferedInputStream getit = new BufferedInputStream( BufferedInputStream getit = new BufferedInputStream(
uc.getInputStream()); uc.getInputStream());
FileOutputStream saveit = new FileOutputStream(destpath); FileOutputStream saveit = new FileOutputStream(f);
BufferedOutputStream bout = new BufferedOutputStream(saveit, BufferedOutputStream bout = new BufferedOutputStream(saveit,
1024); 1024);
byte data[] = new byte[1024]; byte data[] = new byte[1024];
@ -296,8 +295,7 @@ public class RepoXMLHandler extends DefaultHandler {
// APKs are merged into the existing one). // APKs are merged into the existing one).
// Returns null if successful, otherwise an error message to be displayed // Returns null if successful, otherwise an error message to be displayed
// to the user (if there is an interactive user!) // to the user (if there is an interactive user!)
public static String doUpdate(Context ctx, DB.Repo repo, public static String doUpdate(Context ctx, DB.Repo repo, Vector<DB.App> apps) {
Vector<DB.App> apps) {
try { try {
if (repo.pubkey != null) { if (repo.pubkey != null) {
@ -394,8 +392,8 @@ public class RepoXMLHandler extends DefaultHandler {
} }
} catch (SSLHandshakeException sslex) { } catch (SSLHandshakeException sslex) {
Log.e("FDroid", "SSLHandShakeException updating from " + repo.address + ":\n" Log.e("FDroid", "SSLHandShakeException updating from "
+ Log.getStackTraceString(sslex)); + repo.address + ":\n" + Log.getStackTraceString(sslex));
return "A problem occurred while establishing an SSL connection. If this problem persists, AND you have a very old device, you could try using http instead of https for the repo URL."; return "A problem occurred while establishing an SSL connection. If this problem persists, AND you have a very old device, you could try using http instead of https for the repo URL.";
} catch (Exception e) { } catch (Exception e) {
Log.e("FDroid", "Exception updating from " + repo.address + ":\n" Log.e("FDroid", "Exception updating from " + repo.address + ":\n"