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