I'm working on a project that requires the connection of a smartphone to a tablet via a USB cable. To acces the files from the smartphone from the tablet, I am using the Android's Intent.ACTION_GET_CONTENT to retrieve the files. I am, more specifically trying to open pictures.
I know this is possible since, when I click on the notification describing the smartphone, it opens a default Android app with the base folder of the smartphone.
What I am trying to achieve is to directly open the connected smartphone's storage instead of having to switch from the tablet to storage to the smartphone's.
I know how to get the volume name of the smartphone but that hasn't helped me progress. I have checked the Uri, received from the Intent, it is something like content://com.android.mtp.documents/document/951 or content://com.android.mtp.documents/tree/1021.
I have tried to use thes Uri to open the desired folder but it didn't work.
I've tried the new StorageManager API without success.
Recently, I've focused more on trying to simply access the files from my app but using the above mentionned Uri or the mount folder (/dev/bus/usb/001/002/) leads to nothing.
I also tried the Environment.MEDIA_MOUNTED without success.
My current code it this:
Requesting permission to use the smartphone:
final UsbManager manager = (UsbManager) getActivity().getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
if (deviceList.size() > 0) {//TODO switch to 1 on USBCameraFragment
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
UsbDevice device = (UsbDevice) deviceList.values().toArray()[0];
manager.requestPermission(device, mPermissionIntent);
} else {
Toast.makeText(getContext(), "Please connect your device to the tablet.", Toast.LENGTH_SHORT).show();
}
Opening the connection and starting the Intent:
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
Uri path = MediaStore.Files.getContentUri(device.getProductName());
//Uri path = Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.MEDIA_MOUNTED).getAbsolutePath());
i.setDataAndType(path, "image/*");
i.addCategory(Intent.CATEGORY_OPENABLE);
MtpDevice mtpDevice = new MtpDevice(device);
UsbDeviceConnection conn = ((UsbManager) getActivity().getSystemService(Context.USB_SERVICE)).openDevice(device);
mtpDevice.open(conn);
//1.5s to make sure I have allowed the MTP connection on the smartphone.
try{Thread.sleep(1500);}catch(InterruptedException e){}
startActivityForResult(i, Constants.PICKFILE_REQUEST_CODE);
}
}
else {
Log.d(TAG, "permission denied for device: " + device);
}
}
}
}
};
Related
I am working on a device running Android 8.1.0. I'm trying to open an image from a message attachment. I had a cache of image files working using a FileProvider a week ago and now it just stopped working without me touching the code. I'm trying to share an image from my internal app storage to Intent.ACTION_VIEW outside of my app. The photo viewer does launch, but there's a progress circle that just keeps spinning. Any suggestions? Thanks!
void launchViewer(File f) {
Uri uri = FileProvider.getUriForFile(context, "com.company.secure.provider", f);
Intent intent = new Intent(Intent.ACTION_VIEW);
String mimeType = Attachment.getMimeType(f.getName());
//TODO Test to make sure this works on all devices...
if (mimeType.startsWith("video")) {
mimeType = "video/*";
}
if (mimeType.startsWith("image")) {
mimeType = "image/*";
}
if(mimeType==null || mimeType.length()==0) {
unknownMimeType(f.getName());
return;
}
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if(resInfoList==null || resInfoList.size()==0)
{
AlertDialog dialog = new AlertDialog.Builder(context).setTitle("Error")
.setMessage(String.format("Cannot find app to open file type(%s)",mimeType)).show();
return;
}
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setDataAndType(uri, mimeType);
context.startActivity(intent);
}
So I just had to add the following line right before starting the activity.
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
For some reason, the APK I shipped to testing that doesn't have this line in it works... but any new build does not work without this. I read that using the ResolveInfo method will only work for Lollipop and below and you will have to grant the permission directly to the intent. (Not sure how true this is). For this reason I left both permission granting methods in there to cover all bases. Thanks for all the help!
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Inside my app, I want to detect if an app like VLC is installed.
If it does, and when user clicks button, my app will proceed to play a video but if does not, the app will direct user to App store to download the app.
Is there a way to detect if an particular app is installed or not?
Try this:
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(***REPLACE_WITH_YOUR_INTENT***,
PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;
From the Android Docs:
Although the Android platform guarantees that certain intents will
resolve to one of the built-in apps (such as the Phone, Email, or
Calendar app), you should always include a verification step before
invoking an intent.
To verify there is an activity available that can respond to the
intent, call queryIntentActivities() to get a list of activities
capable of handling your Intent. If the returned List is not empty,
you can safely use the intent.
Note: You should perform this check when your activity first starts in
case you need to disable the feature that uses the intent before the
user attempts to use it. If you know of a specific app that can handle
the intent, you can also provide a link for the user to download the
app (see how to link to your product on Google Play).
So, you could use that like this:
Intent vlcIntent = new Intent(Intent.ACTION_VIEW);
vlcIntent.setPackage("org.videolan.vlc");
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(vlcIntent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;
if (isIntentSafe){
startActivity(vlcIntent);
} else {
Intent marketIntent = new Intent(Intent.ACTION_VIEW);
marketIntent.setData(Uri.parse("market://details?id=org.videolan.vlc"));
startActivity(marketIntent);
}
Also, another link that might be useful(VideoLan Wiki):
Android Video Player Intents
It says:
For a simple media playback:
int vlcRequestCode = 42; Uri uri =
Uri.parse("file:///storage/emulated/0/Movies/KUNG FURY Official
Movie.mp4"); Intent vlcIntent = new Intent(Intent.ACTION_VIEW);
vlcIntent.setPackage("org.videolan.vlc");
vlcIntent.setDataAndTypeAndNormalize(uri, "video/*");
vlcIntent.putExtra("title", "Kung Fury");
vlcIntent.putExtra("from_start", false);
vlcIntent.putExtra("position", 90000l);
vlcIntent.putExtra("subtitles_location",
"/sdcard/Movies/Fifty-Fifty.srt"); startActivityForResult(vlcIntent,
vlcRequestCode);
If you specifically want to start VideoPlayerActivity, you can set
vlcIntent.setComponent(new ComponentName("org.videolan.vlc",
"org.videolan.vlc.gui.video.VideoPlayerActivity"));
You could also put the code into a boolean code block and pass in your intent, that way you could reuse the code. Like this:
private boolean checkIntent(Intent intent) {
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;
return isIntentSafe;
}
You will need to check to see if the package for VLC is installed. If it is not installed then open the play store showing the vlc install page.
This is the source:
String appPackageName = "org.videolan.vlc";
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
} catch (android.content.ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}
The source below will check to see if there is anything that can play video and if not, then it will prompt the user to install VLC. This is a more complete example that might help other users. It checks to see if anything locally installed can play the file and then if not, checks for vlc, and if VLC is not installed, then it will take the user to the Play Store.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
intent.setDataAndType(Uri.fromFile(file), mimetype);
PackageManager manager = context.getPackageManager();
List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent, 0);
if (resolveInfoList.size() > 0) {
context.startActivity(intent);
} else {
FragmentManager fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager();
ClassChatRecyclerAdapter.InstallVlcDialogFragment.newInstance(extension).show(fragmentManager, "INSTALL_VLC");
}
This is the dialog that will check for VLC and if it doesn't find it, then it will take the user to the play store to install it. You can take use the try/catch part of the source below to specifically solve your problem.
public static class InstallVlcDialogFragment extends DialogFragment {
public static ClassChatRecyclerAdapter.InstallVlcDialogFragment newInstance(String mediaType) {
ClassChatRecyclerAdapter.InstallVlcDialogFragment frag = new ClassChatRecyclerAdapter.InstallVlcDialogFragment();
Bundle args = new Bundle();
args.putString("mediaType", mediaType);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String mediaType = getArguments().getString("mediaType");
return new AlertDialog.Builder(getActivity(), R.style.AppDialogTheme)
.setTitle("Unable to find video player for " +mediaType + " files.")
.setMessage("Install VLC Player to play file?")
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String appPackageName = "org.videolan.vlc";
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
} catch (android.content.ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}
dismiss();
}
}
)
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dismiss();
}
}
)
.create();
}
}
can anyone give me help:
I have put this code is work well if my app is last app opened. but if I open other app after my app, she's stays in background.
if anyone can give me how I can run my application as if it's the last open application or something else like its.
code:
public void Show_App(String packageName){
this.activity.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
Intent startIntent =
context.getPackageManager().getLaunchIntentForPackage(packageName);
startIntent.setFlags(
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT |
Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
);
this.context.startActivity(startIntent);
}
private void getRecentAppList() {
ActivityManager mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> recentTasks = mActivityManager.getRecentTasks(10, 0);
for (ActivityManager.RecentTaskInfo taskInfo : recentTasks) {
String packagename = task.baseIntent.getComponent().getPackageName();
Intent intent = taskInfo.baseIntent;
ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
ActivityInfo activityInfo = resolveInfo.activityInfo;
} }
you didn't close or clear app in recent list than recent app lunch list is get.
I am developing an Android application which involves showing the user a list of nearby Bluetooth devices and connecting to the device selected by them. I'm trying to use the system bluetooth device picker as shown in these posts:
How to retrieve Bluetooth device info with Android Bluetooth device picker?
Android Bluetooth Device Picker Usage
The device picker does show, but I can't find out which device was selected in my code. The toast inside the onReceive does not show, which suggests that no broadcast is being received.
Another problem I faced is that if I try to start the device picker activity inside the onRequestPermissionsResult, the device picker does not show up at all, despite clicking 'allow' in the request permission dialog. The toast inside doesn't get displayed either.
Here's the code:
//Code inside Fragment
BroadcastReceiver mReceiver;
BluetoothAdapter bluetoothAdapter;
BluetoothSocket bsock;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.controller_mode_layout,container,false);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//Get location access permission.
if (bluetoothAdapter != null) {
if (bluetoothAdapter.isEnabled()) {
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, reqCode);
}
}
//Receiver to get the selected device information
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(this);
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Toast.makeText(context,"Device"+device.getAddress(), Toast.LENGTH_SHORT).show();
try {
bsock=device.createRfcommSocketToServiceRecord(UUID.fromString("00002415-0000-1000-8000-00805F9B34FB"));
bsock.connect();
//Send and receive data logic follows
} catch (IOException e) {
e.printStackTrace();
}
}
};
getActivity().registerReceiver(mReceiver, new IntentFilter("android.bluetooth.devicepicker.action.DEVICE_SELECTED"));
showDevicePicker();
return myView;
}
#Override
public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)
{
Toast.makeText(getActivity(),"Permission result", Toast.LENGTH_SHORT).show();
if((requestCode == reqCode) && (grantResults[0] == PackageManager.PERMISSION_GRANTED))
{
//Not working
// showDevicePicker();
}
}
public void showDevicePicker()
{
//Launch built in bluetooth device picker activity
startActivity( new Intent("android.bluetooth.devicepicker.action.LAUNCH")
.putExtra("android.bluetooth.devicepicker.extra.NEED_AUTH", false)
.putExtra("android.bluetooth.devicepicker.extra.FILTER_TYPE", 0)
.putExtra("android.bluetooth.devicepicker.extra.LAUNCH_PACKAGE","com.example.ankit2.controllerapp1")
.putExtra("android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS","com.example.ankit2.controllerapp1.Fragment1")
.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS));
}
Any help will be appreciated.
Note: I tested the code on a Lenovo K3 note running Marshmallow.
The problem was in the DEVICE_PICKER_LAUNCH_CLASS, which was specified as Fragment1. The launch class must be an activity, even if the broadcast receiver is inside a fragment. In this case, changing the launch class to ControllerActivity (which contains the fragment Fragment1) fixed the problem.
I write a program,which contains broadcast receiver to catch ACTION_MEDIA_MOUNTED,but it works not on all devices. In example: my Meizu m2 note has otg support , and device can open a flash storage,but in my application it not works(no open). In my code,I need to get directory(mass storage directory) path to write or read file.
my broadcast:
public class UsbReceiver extends BroadcastReceiver {
private static final String ACTION_USB_PERMISSION = "com.poudanen.usbchecker.USB_PERMISSION";
#Override
public void onReceive(final Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)) {
Toast.makeText(context, "Media device connected", Toast.LENGTH_SHORT).show();
Uri uriFile = intent.getData();
File dir = new File(uriFile.getPath());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putString("path", uriFile.getPath()).apply();
Toast.makeText(context, "Media device connected", Toast.LENGTH_SHORT).show();
if (dir.canRead()) {
//other code
}
}}