option to send via bluetooth any installed app on the AppDetails page
This takes the code used for sending the FDroid.apk and applies it to any installed app. So the user can go to the AppDetails for any installed app and select "Send via Bluetooth" from the menu, and send the app to another phone.
This commit is contained in:
parent
0db711c08d
commit
4a55cdf938
@ -78,6 +78,7 @@
|
||||
<string name="go_to_nfc_settings">Go to NFC Settings…</string>
|
||||
<string name="bluetooth_activity_not_found">No Bluetooth send method found, choose one!</string>
|
||||
<string name="choose_bt_send">Choose Bluetooth send method</string>
|
||||
<string name="send_via_bluetooth">Send via Bluetooth</string>
|
||||
|
||||
<string name="repo_add_url">Repository address</string>
|
||||
<string name="repo_add_fingerprint">Fingerprint (optional)</string>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user