diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0d0861e7c..b068d0ae9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -78,6 +78,7 @@
Go to NFC Settingsā¦
No Bluetooth send method found, choose one!
Choose Bluetooth send method
+ Send via Bluetooth
Repository address
Fingerprint (optional)
diff --git a/src/org/fdroid/fdroid/AppDetails.java b/src/org/fdroid/fdroid/AppDetails.java
index 51e7fdecb..1e40c9ba1 100644
--- a/src/org/fdroid/fdroid/AppDetails.java
+++ b/src/org/fdroid/fdroid/AppDetails.java
@@ -19,11 +19,6 @@
package org.fdroid.fdroid;
-import java.io.File;
-import java.security.NoSuchAlgorithmException;
-import java.util.Iterator;
-import java.util.List;
-
import android.content.*;
import android.widget.*;
import org.fdroid.fdroid.data.*;
@@ -33,6 +28,7 @@ import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
+import android.bluetooth.BluetoothAdapter;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.os.Build;
@@ -40,6 +36,8 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
+import android.support.v4.app.NavUtils;
+import android.support.v4.view.MenuItemCompat;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageInfo;
@@ -60,26 +58,31 @@ import android.view.View;
import android.view.ViewGroup;
import android.graphics.Bitmap;
-import android.support.v4.app.NavUtils;
-import android.support.v4.view.MenuItemCompat;
-
-import org.fdroid.fdroid.compat.PackageManagerCompat;
-import org.fdroid.fdroid.compat.ActionBarCompat;
-import org.fdroid.fdroid.compat.MenuManager;
-import org.fdroid.fdroid.Utils.CommaSeparatedList;
-
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
+import org.fdroid.fdroid.Utils.CommaSeparatedList;
+import org.fdroid.fdroid.compat.ActionBarCompat;
+import org.fdroid.fdroid.compat.MenuManager;
+import org.fdroid.fdroid.compat.PackageManagerCompat;
+
+import java.io.File;
+import java.security.NoSuchAlgorithmException;
+import java.util.Iterator;
+import java.util.List;
+
public class AppDetails extends ListActivity {
+ private static final String TAG = "AppDetails";
private static final int REQUEST_INSTALL = 0;
private static final int REQUEST_UNINSTALL = 1;
+ public static final int REQUEST_ENABLE_BLUETOOTH = 2;
public static final String EXTRA_APPID = "appid";
public static final String EXTRA_FROM = "from";
+ private FDroidApp fdroidApp;
private ApkListAdapter adapter;
private static class ViewHolder {
@@ -236,6 +239,7 @@ public class AppDetails extends ListActivity {
private static final int DOGECOIN = Menu.FIRST + 12;
private static final int FLATTR = Menu.FIRST + 13;
private static final int DONATE_URL = Menu.FIRST + 14;
+ private static final int SEND_VIA_BLUETOOTH = Menu.FIRST + 15;
private App app;
private String appid;
@@ -255,7 +259,8 @@ public class AppDetails extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
- ((FDroidApp) getApplication()).applyTheme(this);
+ fdroidApp = ((FDroidApp) getApplication());
+ fdroidApp.applyTheme(this);
super.onCreate(savedInstanceState);
@@ -760,6 +765,9 @@ public class AppDetails extends ListActivity {
if (app.donateURL != null)
donate.add(Menu.NONE, DONATE_URL, 10, R.string.menu_website);
}
+ if (app.isInstalled() && fdroidApp.bluetoothAdapter != null) { // ignore on devices without Bluetooth
+ menu.add(Menu.NONE, SEND_VIA_BLUETOOTH, 6, R.string.send_via_bluetooth);
+ }
return true;
}
@@ -850,6 +858,17 @@ public class AppDetails extends ListActivity {
tryOpenUri(app.donateURL);
return true;
+ case SEND_VIA_BLUETOOTH:
+ /*
+ * If Bluetooth has not been enabled/turned on, then
+ * enabling device discoverability will automatically enable Bluetooth
+ */
+ Intent discoverBt = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
+ discoverBt.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 121);
+ startActivityForResult(discoverBt, REQUEST_ENABLE_BLUETOOTH);
+ // if this is successful, the Bluetooth transfer is started
+ return true;
+
}
return super.onOptionsItemSelected(item);
}
@@ -1104,6 +1123,8 @@ public class AppDetails extends ListActivity {
case REQUEST_UNINSTALL:
resetRequired = true;
break;
+ case REQUEST_ENABLE_BLUETOOTH:
+ fdroidApp.sendViaBluetooth(this, resultCode, app.id);
}
}
}
diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java
index f4e912fa2..48b87e76d 100644
--- a/src/org/fdroid/fdroid/FDroid.java
+++ b/src/org/fdroid/fdroid/FDroid.java
@@ -20,18 +20,15 @@
package org.fdroid.fdroid;
import android.annotation.TargetApi;
-import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.NotificationManager;
import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothManager;
import android.content.*;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.net.Uri;
@@ -48,7 +45,6 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
-import android.widget.Toast;
import org.fdroid.fdroid.compat.TabManager;
import org.fdroid.fdroid.data.AppProvider;
@@ -70,8 +66,7 @@ public class FDroid extends FragmentActivity {
private static final int SEARCH = Menu.FIRST + 4;
private static final int BLUETOOTH_APK = Menu.FIRST + 5;
- /* request codes for Bluetooth flows */
- private BluetoothAdapter mBluetoothAdapter = null;
+ private FDroidApp fdroidApp = null;
private ViewPager viewPager;
@@ -80,7 +75,8 @@ public class FDroid extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
- ((FDroidApp) getApplication()).applyTheme(this);
+ fdroidApp = ((FDroidApp) getApplication());
+ fdroidApp.applyTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.fdroid);
@@ -112,18 +108,6 @@ public class FDroid extends FragmentActivity {
Uri uri = AppProvider.getContentUri();
getContentResolver().registerContentObserver(uri, true, new AppObserver());
-
- getBluetoothAdapter();
- }
-
- @TargetApi(18)
- private void getBluetoothAdapter() {
- // to use the new, recommended way of getting the adapter
- // http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
- if (Build.VERSION.SDK_INT < 18)
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- else
- mBluetoothAdapter = ((BluetoothManager) getSystemService(BLUETOOTH_SERVICE)).getAdapter();
}
@Override
@@ -149,7 +133,7 @@ public class FDroid extends FragmentActivity {
android.R.drawable.ic_menu_agenda);
MenuItem search = menu.add(Menu.NONE, SEARCH, 3, R.string.menu_search).setIcon(
android.R.drawable.ic_menu_search);
- if (mBluetoothAdapter != null) // ignore on devices without Bluetooth
+ if (fdroidApp.bluetoothAdapter != null) // ignore on devices without Bluetooth
menu.add(Menu.NONE, BLUETOOTH_APK, 3, R.string.menu_send_apk_bt);
menu.add(Menu.NONE, PREFERENCES, 4, R.string.menu_preferences).setIcon(
android.R.drawable.ic_menu_preferences);
@@ -298,45 +282,7 @@ public class FDroid extends FragmentActivity {
}
break;
case REQUEST_ENABLE_BLUETOOTH:
- if (resultCode == Activity.RESULT_CANCELED)
- break;
- String packageName = null;
- String className = null;
- boolean found = false;
- Intent sendBt = null;
- try {
- PackageManager pm = getPackageManager();
- ApplicationInfo appInfo = pm.getApplicationInfo("org.fdroid.fdroid",
- PackageManager.GET_META_DATA);
- sendBt = new Intent(Intent.ACTION_SEND);
- // The APK type is blocked by stock Android, so use zip
- // sendBt.setType("application/vnd.android.package-archive");
- sendBt.setType("application/zip");
- sendBt.putExtra(Intent.EXTRA_STREAM,
- Uri.parse("file://" + appInfo.publicSourceDir));
- // not all devices have the same Bluetooth Activities, so
- // let's find it
- for (ResolveInfo info : pm.queryIntentActivities(sendBt, 0)) {
- packageName = info.activityInfo.packageName;
- if (packageName.equals("com.android.bluetooth")
- || packageName.equals("com.mediatek.bluetooth")) {
- className = info.activityInfo.name;
- found = true;
- break;
- }
- }
- } catch (NameNotFoundException e1) {
- e1.printStackTrace();
- found = false;
- }
- if (!found) {
- Toast.makeText(this, R.string.bluetooth_activity_not_found,
- Toast.LENGTH_SHORT).show();
- startActivity(Intent.createChooser(sendBt, getString(R.string.choose_bt_send)));
- } else {
- sendBt.setClassName(packageName, className);
- startActivity(sendBt);
- }
+ fdroidApp.sendViaBluetooth(this, resultCode, "org.fdroid.fdroid");
break;
}
}
diff --git a/src/org/fdroid/fdroid/FDroidApp.java b/src/org/fdroid/fdroid/FDroidApp.java
index 4ec114050..b722a1221 100644
--- a/src/org/fdroid/fdroid/FDroidApp.java
+++ b/src/org/fdroid/fdroid/FDroidApp.java
@@ -18,17 +18,31 @@
package org.fdroid.fdroid;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Log;
+import android.widget.Toast;
+
import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.utils.StorageUtils;
+
import de.duenndns.ssl.MemorizingTrustManager;
+
import org.fdroid.fdroid.compat.PRNGFixes;
import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.InstalledAppCacheUpdater;
@@ -44,6 +58,8 @@ import java.security.NoSuchAlgorithmException;
public class FDroidApp extends Application {
+ BluetoothAdapter bluetoothAdapter = null;
+
private static enum Theme {
dark, light
}
@@ -121,6 +137,7 @@ public class FDroidApp extends Application {
}
UpdateService.schedule(getApplicationContext());
+ bluetoothAdapter = getBluetoothAdapter();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.discCache(new LimitedAgeDiscCache(
@@ -179,4 +196,55 @@ public class FDroidApp extends Application {
}
}
+ @TargetApi(18)
+ private BluetoothAdapter getBluetoothAdapter() {
+ // to use the new, recommended way of getting the adapter
+ // http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
+ if (Build.VERSION.SDK_INT < 18)
+ return BluetoothAdapter.getDefaultAdapter();
+ else
+ return ((BluetoothManager) getSystemService(BLUETOOTH_SERVICE)).getAdapter();
+ }
+
+ void sendViaBluetooth(Activity activity, int resultCode, String packageName) {
+ if (resultCode == Activity.RESULT_CANCELED)
+ return;
+ String bluetoothPackageName = null;
+ String className = null;
+ boolean found = false;
+ Intent sendBt = null;
+ try {
+ PackageManager pm = getPackageManager();
+ ApplicationInfo appInfo = pm.getApplicationInfo(packageName,
+ PackageManager.GET_META_DATA);
+ sendBt = new Intent(Intent.ACTION_SEND);
+ // The APK type is blocked by stock Android, so use zip
+ // sendBt.setType("application/vnd.android.package-archive");
+ sendBt.setType("application/zip");
+ sendBt.putExtra(Intent.EXTRA_STREAM,
+ Uri.parse("file://" + appInfo.publicSourceDir));
+ // not all devices have the same Bluetooth Activities, so
+ // let's find it
+ for (ResolveInfo info : pm.queryIntentActivities(sendBt, 0)) {
+ bluetoothPackageName = info.activityInfo.packageName;
+ if (bluetoothPackageName.equals("com.android.bluetooth")
+ || bluetoothPackageName.equals("com.mediatek.bluetooth")) {
+ className = info.activityInfo.name;
+ found = true;
+ break;
+ }
+ }
+ } catch (NameNotFoundException e1) {
+ e1.printStackTrace();
+ found = false;
+ }
+ if (!found) {
+ Toast.makeText(this, R.string.bluetooth_activity_not_found,
+ Toast.LENGTH_SHORT).show();
+ activity.startActivity(Intent.createChooser(sendBt, getString(R.string.choose_bt_send)));
+ } else {
+ sendBt.setClassName(bluetoothPackageName, className);
+ activity.startActivity(sendBt);
+ }
+ }
}