Merge branch 'jmdns-fixes-and-tor-onion-support' into 'master'
Jmdns fixes and tor onion support There are three groups of work in this collection of commits: * improvements to the `WifiStateChangeService` and related activities like JmDNS to eliminate problems that happen when there are a lot of wifi change events. * add rework the `.net.Downloader` stuff to add Tor support and lay the groundwork for Bluetooth support * add support for repos on Tor Hidden Service .onion addresses
This commit is contained in:
commit
95180512c7
@ -4,7 +4,11 @@
|
|||||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="src" path="extern/symlinks-for-ant-and-eclipse"/>
|
<classpathentry kind="src" path="extern/symlinks-for-ant-and-eclipse">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="ignore_optional_problems" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
<classpathentry kind="src" path="gen"/>
|
<classpathentry kind="src" path="gen"/>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPinning"/>
|
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPinning"/>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/MemorizingActivity"/>
|
<classpathentry combineaccessrules="false" kind="src" path="/MemorizingActivity"/>
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
* find local repos on the same network using Bonjour/mDNS
|
* find local repos on the same network using Bonjour/mDNS
|
||||||
|
|
||||||
|
* use FDroid repos on Tor Hidden Services (.onion addresses)
|
||||||
|
|
||||||
* directly send installed apps to other devices via Bluetooth and Android Beam
|
* directly send installed apps to other devices via Bluetooth and Android Beam
|
||||||
(NFC+Bluetooth), also compatible with Samsung/HTC S-Beam
|
(NFC+Bluetooth), also compatible with Samsung/HTC S-Beam
|
||||||
|
|
||||||
|
@ -41,11 +41,13 @@ import com.nostra13.universalimageloader.utils.StorageUtils;
|
|||||||
|
|
||||||
import de.duenndns.ssl.MemorizingTrustManager;
|
import de.duenndns.ssl.MemorizingTrustManager;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.Preferences.ChangeListener;
|
||||||
import org.fdroid.fdroid.compat.PRNGFixes;
|
import org.fdroid.fdroid.compat.PRNGFixes;
|
||||||
import org.fdroid.fdroid.data.AppProvider;
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
import org.fdroid.fdroid.data.InstalledAppCacheUpdater;
|
import org.fdroid.fdroid.data.InstalledAppCacheUpdater;
|
||||||
import org.fdroid.fdroid.data.Repo;
|
import org.fdroid.fdroid.data.Repo;
|
||||||
import org.fdroid.fdroid.localrepo.LocalRepoService;
|
import org.fdroid.fdroid.localrepo.LocalRepoService;
|
||||||
|
import org.fdroid.fdroid.net.IconDownloader;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
import org.thoughtcrime.ssl.pinning.PinningTrustManager;
|
import org.thoughtcrime.ssl.pinning.PinningTrustManager;
|
||||||
import org.thoughtcrime.ssl.pinning.SystemKeyStore;
|
import org.thoughtcrime.ssl.pinning.SystemKeyStore;
|
||||||
@ -151,7 +153,8 @@ public class FDroidApp extends Application {
|
|||||||
bluetoothAdapter = getBluetoothAdapter();
|
bluetoothAdapter = getBluetoothAdapter();
|
||||||
|
|
||||||
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
|
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
|
||||||
.discCache(new LimitedAgeDiscCache(
|
.imageDownloader(new IconDownloader(getApplicationContext()))
|
||||||
|
.diskCache(new LimitedAgeDiscCache(
|
||||||
new File(StorageUtils.getCacheDirectory(getApplicationContext(), true),
|
new File(StorageUtils.getCacheDirectory(getApplicationContext(), true),
|
||||||
"icons"),
|
"icons"),
|
||||||
null,
|
null,
|
||||||
@ -213,6 +216,13 @@ public class FDroidApp extends Application {
|
|||||||
if (wifiState == WifiManager.WIFI_STATE_ENABLING
|
if (wifiState == WifiManager.WIFI_STATE_ENABLING
|
||||||
|| wifiState == WifiManager.WIFI_STATE_ENABLED)
|
|| wifiState == WifiManager.WIFI_STATE_ENABLED)
|
||||||
startService(new Intent(this, WifiStateChangeService.class));
|
startService(new Intent(this, WifiStateChangeService.class));
|
||||||
|
// if the HTTPS pref changes, then update all affected things
|
||||||
|
Preferences.get().registerLocalRepoHttpsListeners(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onPreferenceChange() {
|
||||||
|
startService(new Intent(FDroidApp.this, WifiStateChangeService.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(18)
|
@TargetApi(18)
|
||||||
@ -282,17 +292,21 @@ public class FDroidApp extends Application {
|
|||||||
public static void startLocalRepoService(Context context) {
|
public static void startLocalRepoService(Context context) {
|
||||||
if (!localRepoServiceIsBound) {
|
if (!localRepoServiceIsBound) {
|
||||||
Context app = context.getApplicationContext();
|
Context app = context.getApplicationContext();
|
||||||
app.bindService(new Intent(app, LocalRepoService.class),
|
Intent service = new Intent(app, LocalRepoService.class);
|
||||||
serviceConnection, Context.BIND_AUTO_CREATE);
|
localRepoServiceIsBound = app.bindService(service, serviceConnection,
|
||||||
localRepoServiceIsBound = true;
|
Context.BIND_AUTO_CREATE);
|
||||||
|
if (localRepoServiceIsBound)
|
||||||
|
app.startService(service);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void stopLocalRepoService(Context context) {
|
public static void stopLocalRepoService(Context context) {
|
||||||
|
Context app = context.getApplicationContext();
|
||||||
if (localRepoServiceIsBound) {
|
if (localRepoServiceIsBound) {
|
||||||
context.getApplicationContext().unbindService(serviceConnection);
|
app.unbindService(serviceConnection);
|
||||||
localRepoServiceIsBound = false;
|
localRepoServiceIsBound = false;
|
||||||
}
|
}
|
||||||
|
app.stopService(new Intent(app, LocalRepoService.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void restartLocalRepoService() {
|
public static void restartLocalRepoService() {
|
||||||
|
@ -216,8 +216,18 @@ public class LocalRepoService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void registerMDNSService() {
|
private void registerMDNSService() {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
/*
|
||||||
|
* a ServiceInfo can only be registered with a single instance
|
||||||
|
* of JmDNS, and there is only ever a single LocalHTTPD port to
|
||||||
|
* advertise anyway.
|
||||||
|
*/
|
||||||
|
if (pairService != null || jmdns != null)
|
||||||
|
clearCurrentMDNSService();
|
||||||
String repoName = Preferences.get().getLocalRepoName();
|
String repoName = Preferences.get().getLocalRepoName();
|
||||||
final HashMap<String, String> values = new HashMap<String, String>();
|
HashMap<String, String> values = new HashMap<String, String>();
|
||||||
values.put("path", "/fdroid/repo");
|
values.put("path", "/fdroid/repo");
|
||||||
values.put("name", repoName);
|
values.put("name", repoName);
|
||||||
values.put("fingerprint", FDroidApp.repo.fingerprint);
|
values.put("fingerprint", FDroidApp.repo.fingerprint);
|
||||||
@ -229,12 +239,8 @@ public class LocalRepoService extends Service {
|
|||||||
values.put("type", "fdroidrepo");
|
values.put("type", "fdroidrepo");
|
||||||
type = "_http._tcp.local.";
|
type = "_http._tcp.local.";
|
||||||
}
|
}
|
||||||
pairService = ServiceInfo.create(type, repoName, FDroidApp.port, 0, 0, values);
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
try {
|
||||||
|
pairService = ServiceInfo.create(type, repoName, FDroidApp.port, 0, 0, values);
|
||||||
jmdns = JmDNS.create();
|
jmdns = JmDNS.create();
|
||||||
jmdns.registerService(pairService);
|
jmdns.registerService(pairService);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -249,6 +255,10 @@ public class LocalRepoService extends Service {
|
|||||||
Preferences.get().unregisterLocalRepoBonjourListeners(localRepoBonjourChangeListener);
|
Preferences.get().unregisterLocalRepoBonjourListeners(localRepoBonjourChangeListener);
|
||||||
localRepoBonjourChangeListener = null;
|
localRepoBonjourChangeListener = null;
|
||||||
}
|
}
|
||||||
|
clearCurrentMDNSService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearCurrentMDNSService() {
|
||||||
if (jmdns != null) {
|
if (jmdns != null) {
|
||||||
if (pairService != null) {
|
if (pairService != null) {
|
||||||
jmdns.unregisterService(pairService);
|
jmdns.unregisterService(pairService);
|
||||||
|
@ -22,6 +22,7 @@ package org.fdroid.fdroid.net;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Hasher;
|
import org.fdroid.fdroid.Hasher;
|
||||||
import org.fdroid.fdroid.ProgressListener;
|
import org.fdroid.fdroid.ProgressListener;
|
||||||
import org.fdroid.fdroid.data.Apk;
|
import org.fdroid.fdroid.data.Apk;
|
||||||
@ -172,8 +173,7 @@ public class ApkDownloader implements AsyncDownloadWrapper.Listener {
|
|||||||
Log.d(TAG, "Downloading apk from " + remoteAddress);
|
Log.d(TAG, "Downloading apk from " + remoteAddress);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Downloader downloader = DownloaderFactory.create(remoteAddress, localFile);
|
||||||
Downloader downloader = new HttpDownloader(remoteAddress, localFile);
|
|
||||||
dlWrapper = new AsyncDownloadWrapper(downloader, this);
|
dlWrapper = new AsyncDownloadWrapper(downloader, this);
|
||||||
dlWrapper.download();
|
dlWrapper.download();
|
||||||
return true;
|
return true;
|
||||||
|
@ -14,6 +14,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
public abstract class Downloader {
|
public abstract class Downloader {
|
||||||
|
|
||||||
@ -23,31 +24,32 @@ public abstract class Downloader {
|
|||||||
private ProgressListener progressListener = null;
|
private ProgressListener progressListener = null;
|
||||||
private Bundle eventData = null;
|
private Bundle eventData = null;
|
||||||
private File outputFile;
|
private File outputFile;
|
||||||
|
|
||||||
|
protected URL sourceUrl;
|
||||||
protected String cacheTag = null;
|
protected String cacheTag = null;
|
||||||
|
|
||||||
public static final String EVENT_PROGRESS = "downloadProgress";
|
public static final String EVENT_PROGRESS = "downloadProgress";
|
||||||
|
|
||||||
public abstract InputStream inputStream() throws IOException;
|
public abstract InputStream getInputStream() throws IOException;
|
||||||
|
|
||||||
// The context is required for opening the file to write to.
|
// The context is required for opening the file to write to.
|
||||||
public Downloader(String destFile, Context ctx)
|
Downloader(String destFile, Context ctx)
|
||||||
throws FileNotFoundException, MalformedURLException {
|
throws FileNotFoundException, MalformedURLException {
|
||||||
this(new File(ctx.getFilesDir() + File.separator + destFile));
|
this(new File(ctx.getFilesDir() + File.separator + destFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The context is required for opening the file to write to.
|
// The context is required for opening the file to write to.
|
||||||
public Downloader(Context ctx) throws IOException {
|
Downloader(Context ctx) throws IOException {
|
||||||
this(File.createTempFile("dl-", "", ctx.getCacheDir()));
|
this(File.createTempFile("dl-", "", ctx.getCacheDir()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Downloader(File destFile)
|
Downloader(File destFile)
|
||||||
throws FileNotFoundException, MalformedURLException {
|
throws FileNotFoundException, MalformedURLException {
|
||||||
// http://developer.android.com/guide/topics/data/data-storage.html#InternalCache
|
|
||||||
outputFile = destFile;
|
outputFile = destFile;
|
||||||
outputStream = new FileOutputStream(outputFile);
|
outputStream = new FileOutputStream(outputFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Downloader(OutputStream output)
|
Downloader(OutputStream output)
|
||||||
throws MalformedURLException {
|
throws MalformedURLException {
|
||||||
outputStream = output;
|
outputStream = output;
|
||||||
outputFile = null;
|
outputFile = null;
|
||||||
@ -118,13 +120,13 @@ public abstract class Downloader {
|
|||||||
Log.d(TAG, "Downloading from stream");
|
Log.d(TAG, "Downloading from stream");
|
||||||
InputStream input = null;
|
InputStream input = null;
|
||||||
try {
|
try {
|
||||||
input = inputStream();
|
input = getInputStream();
|
||||||
|
|
||||||
// Getting the input stream is slow(ish) for HTTP downloads, so we'll check if
|
// Getting the input stream is slow(ish) for HTTP downloads, so we'll check if
|
||||||
// we were interrupted before proceeding to the download.
|
// we were interrupted before proceeding to the download.
|
||||||
throwExceptionIfInterrupted();
|
throwExceptionIfInterrupted();
|
||||||
|
|
||||||
copyInputToOutputStream(inputStream());
|
copyInputToOutputStream(getInputStream());
|
||||||
} finally {
|
} finally {
|
||||||
Utils.closeQuietly(outputStream);
|
Utils.closeQuietly(outputStream);
|
||||||
Utils.closeQuietly(input);
|
Utils.closeQuietly(input);
|
||||||
|
32
src/org/fdroid/fdroid/net/DownloaderFactory.java
Normal file
32
src/org/fdroid/fdroid/net/DownloaderFactory.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
package org.fdroid.fdroid.net;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DownloaderFactory {
|
||||||
|
|
||||||
|
public static Downloader create(String url, Context context)
|
||||||
|
throws IOException {
|
||||||
|
if (isOnionAddress(url)) {
|
||||||
|
return new TorHttpDownloader(url, context);
|
||||||
|
} else {
|
||||||
|
return new HttpDownloader(url, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Downloader create(String url, File destFile)
|
||||||
|
throws IOException {
|
||||||
|
if (isOnionAddress(url)) {
|
||||||
|
return new TorHttpDownloader(url, destFile);
|
||||||
|
} else {
|
||||||
|
return new HttpDownloader(url, destFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isOnionAddress(String url) {
|
||||||
|
return url.matches("^[a-zA-Z0-9]+://[^/]+\\.onion/.*");
|
||||||
|
}
|
||||||
|
}
|
@ -7,33 +7,23 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
|
||||||
public class HttpDownloader extends Downloader {
|
public class HttpDownloader extends Downloader {
|
||||||
private static final String TAG = "org.fdroid.fdroid.net.HttpDownloader";
|
private static final String TAG = "org.fdroid.fdroid.net.HttpDownloader";
|
||||||
|
|
||||||
private static final String HEADER_IF_NONE_MATCH = "If-None-Match";
|
protected static final String HEADER_IF_NONE_MATCH = "If-None-Match";
|
||||||
private static final String HEADER_FIELD_ETAG = "ETag";
|
protected static final String HEADER_FIELD_ETAG = "ETag";
|
||||||
|
|
||||||
private URL sourceUrl;
|
protected HttpURLConnection connection;
|
||||||
private HttpURLConnection connection;
|
|
||||||
private int statusCode = -1;
|
private int statusCode = -1;
|
||||||
|
|
||||||
// The context is required for opening the file to write to.
|
// The context is required for opening the file to write to.
|
||||||
public HttpDownloader(String source, String destFile, Context ctx)
|
HttpDownloader(String source, File destFile)
|
||||||
throws FileNotFoundException, MalformedURLException {
|
|
||||||
super(destFile, ctx);
|
|
||||||
sourceUrl = new URL(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The context is required for opening the file to write to.
|
|
||||||
public HttpDownloader(String source, File destFile)
|
|
||||||
throws FileNotFoundException, MalformedURLException {
|
throws FileNotFoundException, MalformedURLException {
|
||||||
super(destFile);
|
super(destFile);
|
||||||
sourceUrl = new URL(source);
|
sourceUrl = new URL(source);
|
||||||
@ -42,20 +32,17 @@ public class HttpDownloader extends Downloader {
|
|||||||
/**
|
/**
|
||||||
* Downloads to a temporary file, which *you must delete yourself when
|
* Downloads to a temporary file, which *you must delete yourself when
|
||||||
* you are done*.
|
* you are done*.
|
||||||
* @see org.fdroid.fdroid.net.HttpDownloader#getFile()
|
* @see org.fdroid.fdroid.net.Downloader#getFile()
|
||||||
*/
|
*/
|
||||||
public HttpDownloader(String source, Context ctx) throws IOException {
|
HttpDownloader(String source, Context ctx) throws IOException {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
sourceUrl = new URL(source);
|
sourceUrl = new URL(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpDownloader(String source, OutputStream output)
|
@Override
|
||||||
throws MalformedURLException {
|
public InputStream getInputStream() throws IOException {
|
||||||
super(output);
|
setupConnection();
|
||||||
sourceUrl = new URL(source);
|
// TODO check out BaseImageDownloader.getStreamFromNetwork() for optims
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream inputStream() throws IOException {
|
|
||||||
return connection.getInputStream();
|
return connection.getInputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,8 +55,25 @@ public class HttpDownloader extends Downloader {
|
|||||||
@Override
|
@Override
|
||||||
public void download() throws IOException, InterruptedException {
|
public void download() throws IOException, InterruptedException {
|
||||||
try {
|
try {
|
||||||
connection = (HttpURLConnection)sourceUrl.openConnection();
|
setupConnection();
|
||||||
|
doDownload();
|
||||||
|
} catch (SSLHandshakeException e) {
|
||||||
|
// TODO this should be handled better, it is not internationalised here
|
||||||
|
throw new IOException(
|
||||||
|
"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." + Log.getStackTraceString(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setupConnection() throws IOException {
|
||||||
|
if (connection != null)
|
||||||
|
return;
|
||||||
|
connection = (HttpURLConnection) sourceUrl.openConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doDownload() throws IOException, InterruptedException {
|
||||||
if (wantToCheckCache()) {
|
if (wantToCheckCache()) {
|
||||||
setupCacheCheck();
|
setupCacheCheck();
|
||||||
Log.i(TAG, "Checking cached status of " + sourceUrl);
|
Log.i(TAG, "Checking cached status of " + sourceUrl);
|
||||||
@ -83,16 +87,9 @@ public class HttpDownloader extends Downloader {
|
|||||||
downloadFromStream();
|
downloadFromStream();
|
||||||
updateCacheCheck();
|
updateCacheCheck();
|
||||||
}
|
}
|
||||||
} catch (SSLHandshakeException e) {
|
|
||||||
// TODO this should be handled better, it is not internationalised here.
|
|
||||||
throw new IOException(
|
|
||||||
"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." + Log.getStackTraceString(e) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isCached() {
|
public boolean isCached() {
|
||||||
return wantToCheckCache() && statusCode == 304;
|
return wantToCheckCache() && statusCode == 304;
|
||||||
}
|
}
|
||||||
|
32
src/org/fdroid/fdroid/net/IconDownloader.java
Normal file
32
src/org/fdroid/fdroid/net/IconDownloader.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
package org.fdroid.fdroid.net;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class IconDownloader extends BaseImageDownloader {
|
||||||
|
|
||||||
|
public IconDownloader(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IconDownloader(Context context, int connectTimeout, int readTimeout) {
|
||||||
|
super(context, connectTimeout, readTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getStream(String imageUri, Object extra) throws IOException {
|
||||||
|
switch (Scheme.ofUri(imageUri)) {
|
||||||
|
case HTTP:
|
||||||
|
case HTTPS:
|
||||||
|
Downloader downloader = DownloaderFactory.create(imageUri, context);
|
||||||
|
return downloader.getInputStream();
|
||||||
|
default:
|
||||||
|
return super.getStream(imageUri, extra);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
src/org/fdroid/fdroid/net/TorHttpDownloader.java
Normal file
32
src/org/fdroid/fdroid/net/TorHttpDownloader.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
package org.fdroid.fdroid.net;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
|
public class TorHttpDownloader extends HttpDownloader {
|
||||||
|
|
||||||
|
TorHttpDownloader(String url, Context ctx) throws IOException {
|
||||||
|
super(url, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
TorHttpDownloader(String url, File destFile)
|
||||||
|
throws FileNotFoundException, MalformedURLException {
|
||||||
|
super(url, destFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupConnection() throws IOException {
|
||||||
|
SocketAddress sa = new InetSocketAddress("127.0.0.1", 8118);
|
||||||
|
Proxy tor = new Proxy(Proxy.Type.HTTP, sa);
|
||||||
|
connection = (HttpURLConnection) sourceUrl.openConnection(tor);
|
||||||
|
}
|
||||||
|
}
|
@ -23,9 +23,14 @@ import java.util.Locale;
|
|||||||
public class WifiStateChangeService extends Service {
|
public class WifiStateChangeService extends Service {
|
||||||
public static final String BROADCAST = "org.fdroid.fdroid.action.WIFI_CHANGE";
|
public static final String BROADCAST = "org.fdroid.fdroid.action.WIFI_CHANGE";
|
||||||
|
|
||||||
|
private static WaitForWifiAsyncTask asyncTask;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
new WaitForWifiAsyncTask().execute();
|
if (asyncTask != null)
|
||||||
|
asyncTask.cancel(true);
|
||||||
|
asyncTask = new WaitForWifiAsyncTask();
|
||||||
|
asyncTask.execute();
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,15 +43,21 @@ public class WifiStateChangeService extends Service {
|
|||||||
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
||||||
try {
|
try {
|
||||||
while (!wifiManager.isWifiEnabled()) {
|
while (!wifiManager.isWifiEnabled()) {
|
||||||
|
if (isCancelled())
|
||||||
|
return null;
|
||||||
Log.i(TAG, "waiting for the wifi to be enabled...");
|
Log.i(TAG, "waiting for the wifi to be enabled...");
|
||||||
Thread.sleep(3000);
|
Thread.sleep(1000);
|
||||||
}
|
}
|
||||||
int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
|
int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
|
||||||
while (ipAddress == 0) {
|
while (ipAddress == 0) {
|
||||||
|
if (isCancelled())
|
||||||
|
return null;
|
||||||
Log.i(TAG, "waiting for an IP address...");
|
Log.i(TAG, "waiting for an IP address...");
|
||||||
Thread.sleep(3000);
|
Thread.sleep(1000);
|
||||||
ipAddress = wifiManager.getConnectionInfo().getIpAddress();
|
ipAddress = wifiManager.getConnectionInfo().getIpAddress();
|
||||||
}
|
}
|
||||||
|
if (isCancelled())
|
||||||
|
return null;
|
||||||
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
||||||
ipAddress = wifiInfo.getIpAddress();
|
ipAddress = wifiInfo.getIpAddress();
|
||||||
FDroidApp.ipAddressString = String.format(Locale.ENGLISH, "%d.%d.%d.%d",
|
FDroidApp.ipAddressString = String.format(Locale.ENGLISH, "%d.%d.%d.%d",
|
||||||
@ -67,6 +78,9 @@ public class WifiStateChangeService extends Service {
|
|||||||
FDroidApp.repo.address = String.format(Locale.ENGLISH, "%s://%s:%d/fdroid/repo",
|
FDroidApp.repo.address = String.format(Locale.ENGLISH, "%s://%s:%d/fdroid/repo",
|
||||||
scheme, FDroidApp.ipAddressString, FDroidApp.port);
|
scheme, FDroidApp.ipAddressString, FDroidApp.port);
|
||||||
|
|
||||||
|
if (isCancelled())
|
||||||
|
return null;
|
||||||
|
|
||||||
Context context = WifiStateChangeService.this.getApplicationContext();
|
Context context = WifiStateChangeService.this.getApplicationContext();
|
||||||
LocalRepoKeyStore localRepoKeyStore = LocalRepoKeyStore.get(context);
|
LocalRepoKeyStore localRepoKeyStore = LocalRepoKeyStore.get(context);
|
||||||
Certificate localCert = localRepoKeyStore.getCertificate();
|
Certificate localCert = localRepoKeyStore.getCertificate();
|
||||||
@ -75,6 +89,9 @@ public class WifiStateChangeService extends Service {
|
|||||||
lrm.setUriString(FDroidApp.repo.address);
|
lrm.setUriString(FDroidApp.repo.address);
|
||||||
lrm.writeIndexPage(Utils.getSharingUri(context, FDroidApp.repo).toString());
|
lrm.writeIndexPage(Utils.getSharingUri(context, FDroidApp.repo).toString());
|
||||||
|
|
||||||
|
if (isCancelled())
|
||||||
|
return null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Once the IP address is known we need to generate a self
|
* Once the IP address is known we need to generate a self
|
||||||
* signed certificate to use for HTTPS that has a CN field set
|
* signed certificate to use for HTTPS that has a CN field set
|
||||||
|
@ -13,7 +13,7 @@ import org.fdroid.fdroid.data.App;
|
|||||||
import org.fdroid.fdroid.data.Repo;
|
import org.fdroid.fdroid.data.Repo;
|
||||||
import org.fdroid.fdroid.data.RepoProvider;
|
import org.fdroid.fdroid.data.RepoProvider;
|
||||||
import org.fdroid.fdroid.net.Downloader;
|
import org.fdroid.fdroid.net.Downloader;
|
||||||
import org.fdroid.fdroid.net.HttpDownloader;
|
import org.fdroid.fdroid.net.DownloaderFactory;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import org.xml.sax.XMLReader;
|
import org.xml.sax.XMLReader;
|
||||||
@ -89,7 +89,7 @@ abstract public class RepoUpdater {
|
|||||||
protected Downloader downloadIndex() throws UpdateException {
|
protected Downloader downloadIndex() throws UpdateException {
|
||||||
Downloader downloader = null;
|
Downloader downloader = null;
|
||||||
try {
|
try {
|
||||||
downloader = new HttpDownloader(getIndexAddress(), context);
|
downloader = DownloaderFactory.create(getIndexAddress(), context);
|
||||||
downloader.setCacheTag(repo.lastetag);
|
downloader.setCacheTag(repo.lastetag);
|
||||||
|
|
||||||
if (progressListener != null) { // interactive session, show progress
|
if (progressListener != null) { // interactive session, show progress
|
||||||
|
Loading…
x
Reference in New Issue
Block a user