I am trying to open zoom app by passing uri to the intent with below and it works fine.
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("<zoom url>"))
val packageManager = packageManager
if (intent.resolveActivity(packageManager) != null) {
startActivity(launchApp)
}
But this shows my browser also as user can select it and open the uri I pass. what I want to do is only open zoom app with the uri.
By using val activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY) I can filter the apps that can open my intent but how can I select the exact app(zoom) and pass uri to it and open zoom app only with my meeting url?
May be need a packageName?
I referenced some code from Google in this
public static void openCustomTab(Activity activity,
CustomTabsIntent customTabsIntent,
Uri uri,
CustomTabFallback fallback) {
String packageName = CustomTabsHelper.getPackageNameToUse(activity);
//If we cant find a package name, it means theres no browser that supports
//Chrome Custom Tabs installed. So, we fallback to the webview
if (packageName == null) {
if (fallback != null) {
fallback.openUri(activity, uri);
}
} else {
customTabsIntent.intent.setPackage(packageName);
customTabsIntent.launchUrl(activity, uri);
}
}
it use setPackage(),then the app will open the chrome app without chooser.
This is the method of getPackageNameToUse
static final String STABLE_PACKAGE = "com.android.chrome";
static final String BETA_PACKAGE = "com.chrome.beta";
static final String DEV_PACKAGE = "com.chrome.dev";
static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
...
...
public static String getPackageNameToUse(Context context) {
if (sPackageNameToUse != null) return sPackageNameToUse;
PackageManager pm = context.getPackageManager();
// Get default VIEW intent handler.
Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
String defaultViewHandlerPackageName = null;
if (defaultViewHandlerInfo != null) {
defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName;
}
// Get all apps that can handle VIEW intents.
List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
List<String> packagesSupportingCustomTabs = new ArrayList<>();
for (ResolveInfo info : resolvedActivityList) {
Intent serviceIntent = new Intent();
serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
serviceIntent.setPackage(info.activityInfo.packageName);
if (pm.resolveService(serviceIntent, 0) != null) {
packagesSupportingCustomTabs.add(info.activityInfo.packageName);
}
}
// Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
// and service calls.
if (packagesSupportingCustomTabs.isEmpty()) {
sPackageNameToUse = null;
} else if (packagesSupportingCustomTabs.size() == 1) {
sPackageNameToUse = packagesSupportingCustomTabs.get(0);
} else if (!TextUtils.isEmpty(defaultViewHandlerPackageName)
&& !hasSpecializedHandlerIntents(context, activityIntent)
&& packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) {
sPackageNameToUse = defaultViewHandlerPackageName;
} else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
sPackageNameToUse = STABLE_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
sPackageNameToUse = BETA_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
sPackageNameToUse = DEV_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
sPackageNameToUse = LOCAL_PACKAGE;
}
return sPackageNameToUse;
}
Maybe it will help you.
Related
I'm working on uploading file to WebView.
Local files work well. But files from google drive do not work.
URI information of local file is not empty.(not null)
Local file : content://com.android.providers.downloads.documents/document/xxx
Google Drive File : content://com.google.android.apps.docs.storage/document/xxx
This is my code.
...
takeFileResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
int resultCode = result.getResultCode();
if (resultCode == RESULT_OK) {
Intent intent = result.getData();
Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileChooserDialog.class.getSimpleName());
if (fragment instanceof DialogFragment) {
((DialogFragment) fragment).dismiss();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (null == uploadValueCallBack) {
return;
}
if (intent != null) {
Uri uri = intent.getData();
intent.setData(uri);
}
uploadUris = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
uploadValueCallBack.onReceiveValue(uploadUris);
uploadValueCallBack = null;
} else if (null != uploadMessage) {
Uri resultUri = (intent == null) ? null : intent.getData();
uploadMessage.onReceiveValue(resultUri);
uploadMessage = null;
}
}
});
...
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
String[] fileMimeTypes = {
"application/pdf",
"application/zip",
"image/*",
};
i.setType("*/*");
i.putExtra(EXTRA_MIME_TYPES, fileMimeTypes);
takeFileResultLauncher.launch(Intent.createChooser(i, "File Chooser"));
...
I dont know the reason that happens.
Maybe do I have to check the webpage??
please help me... :(
I saved the google drive file locally and send that local uri to webview.
Intent intent = new Intent();
intent.setData(Uri.fromFile(savedLocalFile(uri));
WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
The savedLocalFile() function returns a File stored in local(or external) storage.
If you have any better ideas, please give leave comments.
I am using the following code to check if camera & storage permissions have been granted when user clicks on input-file field on my website in android webview:
public boolean file_permission(){
if(Build.VERSION.SDK_INT >=23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
return false;
}else{
return true;
}
}
class MyWebChromeClient extends WebChromeClient {
// Handling onshow file chooser
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if(file_permission() && Build.VERSION.SDK_INT >= 21) {
file_path = filePathCallback;
Intent takePictureIntent = null;
takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = create_image();
takePictureIntent.putExtra("PhotoPath", cam_file_data);
} catch (IOException ex) {
Log.e(TAG, "Image file creation failed", ex);
}
if (photoFile != null) {
cam_file_data = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
} else {
cam_file_data = null;
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType(file_type);
Intent[] intentArray;
intentArray = new Intent[]{takePictureIntent};
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Select Photo for yourPrint");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, file_req_code);
return true;
} else {
return false;
}
}
}
When the permission is checked via file_permission(), the accept permission dialog appears. But once the user accepts the permission, the input-file field needs to be clicked again by the user to show the file chooser. I want the input-field that originally triggered the onShowFileChooser to be clicked again automatically after user accepts the permissions, so that file chooser opens automatically.
I have tried using onRequestPermissionsResult with javascript to trigger click on input field after permissions acceptance using this code javascript:jQuery('.file-input-field').trigger('click'), However, I do not want to use this way as chrome blocks programmatic clicks on input fields with type file for security purposes.
How to accomplish this?
you must reset this variable like this in java/kotlin :
filePathCallback.onReceiveValue(null)
filePathCallback = null
if filePathCallback not null onShowFileChooser will not triggered
I followed this simple app AndroidScannerDemo which has two main button open camera and open gallery. The Camera is working fine on my phone API 19, but when I try to launch the camera on other devices or emulator the app crash.
From what I could understand this could be due to permission
Edit : Apparently this was asked here awhile ago as well but the issue remain
Wrong Update : the root problem coming from createImageFile method
I tried changing
//cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempFileUri); to
cameraIntent.putExtra(ScanConstants.OPEN_INTENT_PREFERENCE, preference);
I'm able to start the camera but I get crash right after taking picture
Update 2 : I'm trying following this article provided the answer below the only issue I'm using fragment
So How do I change this line
tempFileUri = FileProvider.getUriForFile(getActivity().getApplicationContext(),
"com.scanlibrary.provider", // As defined in Manifest
file);
to
tempFileUri = FileProvider.getUriForFile(PickImageFragment.this,
getString(R.string.file_provider_authority),
file); inside a fragment !
Wrong First argument PickImageFragment
EDIT : Changed openCamera() method inside PickImageFragment
What Im I missing ?
Stack trace
2019-11-29 23:45:05.750 27993-27993/com.nabeeltech.capturedoc E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.nabeeltech.capturedoc, PID: 27993
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nabeeltech.capturedoc/com.scanlibrary.ScanActivity}: java.lang.SecurityException: UID 10091 does not have permission to content://com.scanlibrary.provider/external_files/scanSample/IMG_20191129_224505.jpg [user 0]
Caused by: java.lang.SecurityException: UID 10091 does not have permission to content://com.scanlibrary.provider/external_files/scanSample/IMG_20191129_224505.jpg [user 0]
at com.scanlibrary.PickImageFragment.openCamera(PickImageFragment.java:131)
at com.scanlibrary.PickImageFragment.handleIntentPreference(PickImageFragment.java:79)
at com.scanlibrary.PickImageFragment.init(PickImageFragment.java:60)
at com.scanlibrary.PickImageFragment.onCreateView(PickImageFragment.java:50)
PickImageFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.pick_image_fragment, null);
init();
return view;
}
private void init() {
cameraButton = (ImageButton) view.findViewById(R.id.cameraButton);
cameraButton.setOnClickListener(new CameraButtonClickListener());
galleryButton = (ImageButton)
view.findViewById(R.id.selectButton);
galleryButton.setOnClickListener(new GalleryClickListener());
if (isIntentPreferenceSet()) {
handleIntentPreference();
} else {
getActivity().finish();
}
}
private void handleIntentPreference() {
int preference = getIntentPreference();
if (preference == ScanConstants.OPEN_CAMERA) {
openCamera();
} else if (preference == ScanConstants.OPEN_MEDIA) {
openMediaContent();
}
}
public void openCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri tempFileUri = null;
File file = createImageFile();
boolean isDirectoryCreated = file.getParentFile().mkdirs();
Log.d("", "openCamera: isDirectoryCreated: " + isDirectoryCreated);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
tempFileUri = FileProvider.getUriForFile(getActivity().getApplicationContext(),
"com.scanlibrary.provider", // As defined in Manifest
file);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempFileUri);
} else {
tempFileUri = Uri.fromFile(file);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempFileUri);
}
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
cameraIntent.setClipData(ClipData.newRawUri("", tempFileUri));
cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
startActivityForResult(cameraIntent, ScanConstants.START_CAMERA_REQUEST_CODE);
private File createImageFile() {
clearTempImages();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new
Date());
File file = new File(ScanConstants.IMAGE_PATH, "IMG_" + timeStamp +
".jpg");
fileUri = Uri.fromFile(file);
return file;
}
private void clearTempImages() {
try {
File tempFolder = new File(ScanConstants.IMAGE_PATH);
for (File f : tempFolder.listFiles())
f.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
ScanConstants
public class ScanConstants {
public final static int PICKFILE_REQUEST_CODE = 1;
public final static int START_CAMERA_REQUEST_CODE = 2;
public final static String OPEN_INTENT_PREFERENCE = "selectContent";
public final static String IMAGE_BASE_PATH_EXTRA = "ImageBasePath";
public final static int OPEN_CAMERA = 4;
public final static int OPEN_MEDIA = 5;
public final static String SCANNED_RESULT = "scannedResult";
public final static String IMAGE_PATH = Environment
.getExternalStorageDirectory().getPath() + "/scanSample";
public final static String SELECTED_BITMAP = "selectedBitmap";
}
You've written the code Fileprovider.getUriforFile which is fine, but have you declare the permissions required.
The only way to solve this is to grant permissions to all of the packages that might need it, like this:
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
If above doesn't solve issue i'd suggest to refer this article by Lorenzo Quiroli that solves this issue for older Android versions.
He discovered that you need to manually set the ClipData of the Intent and set the permissions for it, like so:
if ( Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP ) {
takePictureIntent.setClipData( ClipData.newRawUri( "", photoURI ) );
takePictureIntent.addFlags( Intent.FLAG_GRANT_WRITE_URI_PERMISSION|Intent.FLAG_GRANT_READ_URI_PERMISSION );
}
I have set up a Broadcast that starts up when Application is installed with startActivityForResult(). The installation Intent is created here.
private static Intent getOpenDownloadedApkIntent(Context context, File file) {
String name = getPackageNameForAPK(file.getPath(), context);
if (name != null) {
INSTALL_APK_INFO.put(name, file);
}
// The type of intent to use to open the downloaded apk changed in Android N (7.0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri path = FileProvider.getUriForFile(context,
context.getApplicationContext().getPackageName() + ".utils.DownloadedFileProvider",
file);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
intent.setData(path);
return intent;
} else {
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
return intent;
}
}
private static String getPackageNameForAPK(final String archiveFilePath, Context context) {
try {
PackageInfo info = context.getPackageManager().getPackageArchiveInfo(archiveFilePath, PackageManager.GET_META_DATA);
return info.packageName;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
Now if it is Android 7 or higher, then the uninstall works, but if it is Android 6 or lower, then it just seems to delete the icon of the APK but not the APK itself.
Here is the code that should delete the APK:
private static BroadcastReceiver onInstallComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
ApplicationInfo info = null;
try {
info = context.getPackageManager().getApplicationInfo(intent.getDataString().split(":")[1], PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException ex) {
}
try {
if (info != null) {
File file = INSTALL_APK_INFO.get(info.packageName);
if (file != null) {
file.delete();
INSTALL_APK_INFO.remove(info.packageName);
}
}
} catch (NullPointerException ex) {
}
}
};
I am guessing that is has something to do with the path, but at the same time it seems to delete the icon of the APK. By icon I mean that if i remove the file.delete() then the APK is with icon in downloads folder but if I run the file.delete() then the APK is without the icon.
What am I doing wrong?
Do u mean to say that app is getting installed but without launcher icon?
i have read several already answered article on this site and used this
Sending message through WhatsApp
i am able to share from chrome but not from app.
my code is
public void onClickWhatsApp(View view) {
PackageManager pm=getPackageManager();
try {
Intent waIntent = new Intent(Intent.ACTION_SEND);
waIntent.setType("text/plain");
String text = "YOUR TEXT HERE";
PackageInfo info=pm.getPackageInfo("com.whatsapp", PackageManager.GET_META_DATA);
//Check if package exists or not. If not then code
//in catch block will be called
waIntent.setPackage("com.whatsapp");
waIntent.putExtra(Intent.EXTRA_TEXT, text);
startActivity(Intent.createChooser(waIntent, "Share with"));
} catch (NameNotFoundException e) {
Toast.makeText(MainActivity.this, "WhatsApp not Installed", Toast.LENGTH_SHORT).show();
}
}
when i click on share button in my android app whatsapp icon it gives error page not found but when same thing is shared from chrome it just works fine.
my url is http://way2enjoy.com/app/jokes.php
if anyone can guide where the mistake is i will be thankful
you can use my code which works for me
void openWhatsappContact(String number) {
Uri uri = Uri.parse("smsto:" + number);
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.setPackage("com.whatsapp");
startActivity(Intent.createChooser(i, ""));}
enjoy your code time:)
you can use this code also
//method used to show IMs
private void show_custom_chooser(String value) {
List<ResolveInfo> list = null;
final Intent email = new Intent(Intent.ACTION_SEND);
email.setData(Uri.parse("sms:"));
email.putExtra(Intent.EXTRA_TEXT, "" + value);
email.setType("text/plain"); // vnd.android-dir/mms-sms
WindowManager.LayoutParams WMLP = dialogCustomChooser.getWindow()
.getAttributes();
WMLP.gravity = Gravity.CENTER;
dialogCustomChooser.getWindow().setAttributes(WMLP);
dialogCustomChooser.getWindow().setBackgroundDrawable(
new ColorDrawable(android.graphics.Color.TRANSPARENT));
dialogCustomChooser.setCanceledOnTouchOutside(true);
dialogCustomChooser.setContentView(R.layout.about_dialog);
dialogCustomChooser.setCancelable(true);
ListView lvOfIms = (ListView) dialogCustomChooser
.findViewById(R.id.listView1);
PackageManager pm = getPackageManager();
List<ResolveInfo> launchables = pm.queryIntentActivities(email, 0);
// ////////////new
list = new ArrayList<ResolveInfo>();
for (int i = 0; i < launchables.size(); i++) {
String string = launchables.get(i).toString();
Log.d("heh", string);
//check only messangers
if (string.contains("whatsapp")) {
list.add(launchables.get(i));
}
}
Collections.sort(list, new ResolveInfo.DisplayNameComparator(pm));
int size = launchables.size();
adapter = new AppAdapter(pm, list, MainActivity.this);
lvOfIms.setAdapter(adapter);
lvOfIms.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
ResolveInfo launchable = adapter.getItem(position);
ActivityInfo activity = launchable.activityInfo;
ComponentName name = new ComponentName(
activity.applicationInfo.packageName, activity.name);
email.addCategory(Intent.CATEGORY_LAUNCHER);
email.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
email.setComponent(name);
startActivity(email);
dialogCustomChooser.dismiss();
}
});
dialogCustomChooser.show();
}