why Intent.EXTRA_INITIAL_INTENTS not working in android 10 - android

I am trying to share some text, In Android 10 always show max 3 apps in my mobile have WhatsApp but this not displaying here
This code is properly working in below 10 devices but could not find the reason why in android 10 is filtering out.
fun onShareClick() {
val intentShareList = ArrayList<Intent>()
val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND
shareIntent.type = "text/plain"
val resolveInfoList = packageManager.queryIntentActivities(shareIntent, 0)
for (resInfo in resolveInfoList) {
val packageName = resInfo.activityInfo.packageName
val name = resInfo.activityInfo.name
if (packageName.contains("com.facebook") ||
packageName.contains("com.twitter.android") ||
packageName.contains("com.google.android.gm") ||
packageName.contains("com.android.mms") ||
packageName.contains("com.whatsapp")
) {
val intent = Intent()
intent.component = ComponentName(packageName, name)
intent.action = Intent.ACTION_SEND
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_SUBJECT, "Your Subject")
intent.putExtra(Intent.EXTRA_TEXT, "Your Content")
intentShareList.add(intent)
}
}
if (intentShareList.isEmpty()) {
Toast.makeText(this#MainActivity, "No apps to share !", Toast.LENGTH_SHORT).show()
} else {
val chooserIntent = Intent.createChooser(intentShareList.removeAt(0), "Share via")
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS,
intentShareList.toTypedArray()
)
startActivity(chooserIntent)
}
}
In the intentShareList contains WhatsApp info but not displaying

I had the same issue. It seems the problem is in some Android 10 devices (like Samsung), not all. I solved using Intent.EXTRA_EXCLUDE_COMPONENTS instead of Intent.EXTRA_INITIAL_INTENTS, and creating an array of ComponentName to be excluded. Refactoring your code:
fun onShareClick() {
val excludedComponents = ArrayList<ComponentName>()
val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND
shareIntent.type = "text/plain"
val resolveInfoList = packageManager.queryIntentActivities(shareIntent, 0)
for (resInfo in resolveInfoList) {
val packageName = resInfo.activityInfo.packageName
val name = resInfo.activityInfo.name
if (!(packageName.contains("com.facebook") ||
packageName.contains("com.twitter.android") ||
packageName.contains("com.google.android.gm") ||
packageName.contains("com.android.mms") ||
packageName.contains("com.whatsapp"))
) {
excludedComponents.add(ComponentName(packageName, name))
}
}
if (excludedComponents.size()==resolveInfoList.size()) {
Toast.makeText(this#MainActivity, "No apps to share !", Toast.LENGTH_SHORT).show()
} else {
val chooserIntent = Intent.createChooser(shareIntent , "Share via")
chooserIntent.putExtra(
Intent.EXTRA_EXCLUDE_COMPONENTS,
excludedComponents.toTypedArray()
)
startActivity(chooserIntent)
}
}

I think you should create your chooser using the initial intent and add your intentShareList as extra, like this:
val chooserIntent = Intent.createChooser(shareIntent, "Share via")
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS,
intentShareList.toTypedArray()
)
startActivity(chooserIntent)
I think it will bring what you want. Let me know if it helps :)
EDIT: Even if you put on your shareIntent a inicial EXTRA_INTENT and a type, Android Q will ignore what you added on EXTRA_INITIAL_INTENTS, so it wont help
I was reading about this on that issue and I think it wont be fixed, take a look = https://issuetracker.google.com/issues/134367295
Also, there some information on documentation that says using EXTRA_INITIAL_INTENTS to personalized data is not recomended, and its was made to helping share links and it can reduce the apps who will appear, take a look = https://developer.android.com/training/sharing/send
Well, Im very sad about that, Idk what do to also, maybe a unique text... :(

My answer may not answer OP's question but if you want to exclude a specified package, you can refer to it. This solution also works on pre-Android 11 OS.
For me, EXTRA_INITIAL_INTENTS doesn't work on Android 11. So I handled 2 flows for 2 cases (Android 11 or later and pre-Android).
The below code will exclude Facebook out of share options.
1. Add the Facebook package to Android Manifest for expanding package visibility on Android 11. You can check out
<manifest ...>
...
<queries>
...
<package android:name="com.facebook.katana" />
</queries>
...
</manifest>
2. Create an intent chooser:
private fun getShareChooserWithoutFacebook(
context: Context,
template: Intent
): Intent {
// get available share intents
val targets: MutableList<Intent> = mutableListOf()
val candidates: List<ResolveInfo> =
context.packageManager.queryIntentActivities(template, 0)
val excludedComponents = ArrayList<ComponentName>()
// remove facebook which has a broken share intent
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R) {
for (candidate in candidates) {
val packageName = candidate.activityInfo.packageName
if (!packageName.equals("com.facebook.katana")) {
val target = Intent(Intent.ACTION_SEND)
target.type = "text/plain"
target.putExtra(
Intent.EXTRA_SUBJECT,
template.getStringExtra(Intent.EXTRA_SUBJECT)
)
target.putExtra(
Intent.EXTRA_TEXT,
template.getStringExtra(Intent.EXTRA_TEXT)
)
target.setPackage(packageName)
targets.add(target)
}
}
} else {
for (candidate in candidates) {
val packageName = candidate.activityInfo.packageName
val name = candidate.activityInfo.name
if ((packageName.equals("com.facebook.katana"))) {
excludedComponents.add(ComponentName(packageName, name))
}
}
}
var chooserIntent = Intent.createChooser(template, context.getString(R.string.settings_send_via))
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R) {
chooserIntent =
Intent.createChooser(targets.removeAt(0), context.getString(R.string.settings_send_via))
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS,
targets.toTypedArray()
)
} else {
chooserIntent.putExtra(
Intent.EXTRA_EXCLUDE_COMPONENTS,
excludedComponents.toTypedArray()
)
}
return chooserIntent
}
3. Open the intent chooser
fun openShareChooser(context: Context, title: String?, content: String?) {
val template = Intent(Intent.ACTION_SEND)
template.type = "text/plain"
template.putExtra(Intent.EXTRA_SUBJECT, title)
template.putExtra(Intent.EXTRA_TEXT, content)
context.startActivity(
getShareChooserWithoutFacebook(context, template)
)
}

Related

How to open a file in another app via an Intent using an URI?

In my app, I have several file Uri (NOT URI) store. These are of the form:
content://com.android.providers.downloads.documents/document/427
My intention is, once I click a button, open one of these Uri in a file reader (may it be MS Word, Excel, PDF Reader... depending on the extension and device).
I am currently trying this snippet:
val file = File(Uri.parse(uri).path!!)
val myMime: MimeTypeMap = MimeTypeMap.getSingleton()
val newIntent = Intent(Intent.ACTION_VIEW)
val mimeType: String = myMime.getMimeTypeFromExtension(file.extension).toString()
newIntent.setDataAndType(
FileProvider.getUriForFile(applicationContext, "${applicationContext.packageName}.provider", file), mimeType)
newIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
newIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
try {
startActivity(newIntent)
} catch (e: ActivityNotFoundException) {
}
But every time I try to open it, I get:
java.lang.IllegalArgumentException: Failed to find configured root that contains /document/427
Could you please tell me what am I missing? No answers I've found here targeted my problem. Thanks in advance!
UPDATE
Thanks to #CommonsWare help, I managed to avoid an Exception, my code now looks like this:
val newIntent = Intent(Intent.ACTION_VIEW)
newIntent.addCategory(Intent.CATEGORY_OPENABLE)
newIntent.data = Uri.parse(uri)
newIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
newIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
try {
startActivity(newIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show()
}
I'm getting the Uri from here:
val fileResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
viewModel.uploadFile(result, false)
}
fileFab.setOnClickListener {
val intent = Intent()
intent.type = "application/*"
intent.action = Intent.ACTION_OPEN_DOCUMENT
fileResultLauncher.launch(intent)
}
Unfortunately, I'm getting a NoActivityFoundException
Get rid of:
val file = File(Uri.parse(uri).path!!)
...and replace your setDataAndType() call with:
newIntent.setDataAndType(Uri.parse(uri), mimeType)

Share Button In Compose

How can I make a share button in compose, which will share a download link,
I tried this but the result was different that I expected.
Here is the code.
Button(
onClick = {
val intent = Intent(Intent.ACTION_SEND)
.putExtra("File Download Link", downloadUrl.value)
.setType("text/plain")
context.startActivity(Intent.createChooser(intent, "Share Using"))
},
and this is how I am getting the downloadUrl value
val downloadUrl = remember { mutableStateOf("") }
val context = LocalContext.current
val launcher =
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
val task = firebaseUpload(uri, context)
task.addOnCompleteListener {
if (task.isSuccessful) {
downloadUrl.value = task.result.toString()
}
}
}
The downloadUrl value is right but when I copied it in the emulator it was copying the modifier.
you can use this code sample:
onShareClick = {
val context = LocalContext.current
val type = "text/plain"
val subject = "Your subject"
val extraText = "https://www.google.com/codes/${variable.id}"
val shareWith = "ShareWith"
val intent = Intent(Intent.ACTION_SEND)
intent.type = type
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
intent.putExtra(Intent.EXTRA_TEXT, extraText)
ContextCompat.startActivity(
context,
Intent.createChooser(intent, shareWith),
null
)
}

Android Image Share to Another App Where is problem?

Im doing an app and i want to share photo just i saved to phone to another apps like instagram twitter.Im not able to do it and i cant see where the mistake is.Here is my code
`private fun getScreenshot(currentPage: Int){
QuickShot.of(requireActivity().findViewById<ConstraintLayout(currentPage))
.setResultListener(this)
.enableLogging()
.setFilename("screen")
.setPath("Spotibud")
.toJPG()
.save()
}
override fun onQuickShotSuccess(path: String?) {
Log.d(TAG, "onQuickShotSuccess: $path")
shareOnInstagram(path!!)
}
override fun onQuickShotFailed(path: String?, errorMsg: String?) {
Log.d(TAG, "onQuickShotFailed: $errorMsg")
}
private fun shareOnInstagram(path: String){
val stickerAssetUri: Uri = Uri.parse(path)
val intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM,stickerAssetUri)
type = "image/*"
}
startActivity(intent)
}`
and my log when app saves image
2021-02-18 17:28:08.750 16355-16355/com.example.contestifyfirsttry D/Home Fragment: onQuickShotSuccess: /Pictures/Spotibud/screen.jpg
also is there any code how i can see error.try catch not worked
now i found the solution this isnt best practice but im sure it makes you to see what you should do
private fun shareOnInstagram(path: String){
var file : File = File("/storage/emulated/0/Pictures/Spotibud/screen.jpg")
if (file.exists()){
Log.d(TAG, "shareOnInstagram: file exists")
val stickerAssetUri: Uri = Uri.fromFile(file)
val sourceApplication = "com.example.contestifyfirsttry"
val intent = Intent("com.instagram.share.ADD_TO_STORY")
intent.putExtra("source_application", sourceApplication)
intent.type = "image/*"
intent.putExtra("interactive_asset_uri", stickerAssetUri)
intent.putExtra("top_background_color", "#33FF33")
intent.putExtra("bottom_background_color", "#FF00FF")
val activity: Activity? = activity
activity!!.grantUriPermission(
"com.instagram.android", stickerAssetUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
)
if (activity!!.packageManager.resolveActivity(intent, 0) != null) {
activity!!.startActivityForResult(intent, 0)
}
}else{
Log.d(TAG, "shareOnInstagram: file dont exists")
}
}

Android Shortcut is not working in VIVO 10

I implementing shortcut in my app but this is not working in VIVO 10( Funtouch OS). Please help me. I am already used many method but not success.
Method 1: I am using this code but not working
#SuppressLint("NewApi")
private fun shortcut(){
val shortcutManager = getSystemService(ShortcutManager::class.java)
val nhentaiIntent = Intent(this, MainActivity::class.java)
nhentaiIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
nhentaiIntent.action = Intent.ACTION_VIEW
if (shortcutManager!!.isRequestPinShortcutSupported) {
val pinShortcutInfo = ShortcutInfo.Builder(this, "my-shortcut")
.setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher))
.setShortLabel("hello Shortcut")
.setIntent(nhentaiIntent)
.build()
val pinnedShortcutCallbackIntent = shortcutManager.createShortcutResultIntent(pinShortcutInfo)
val successCallback = PendingIntent.getBroadcast(this, /* request code */ 0, pinnedShortcutCallbackIntent, /* flags */ 0)
shortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.intentSender)
}
}
Method 2: I am also used this code but not working
Intent nhentaiIntent = new Intent(context, MainActivity.class);
nhentaiIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
nhentaiIntent.setAction(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
if (shortcutManager.isRequestPinShortcutSupported()) {
ShortcutInfo info = new ShortcutInfo.Builder(context, "Shortcut")
.setIntent(nhentaiIntent)
.setIcon(Icon.createWithResource(context, R.mipmap.ic_launcher))
.setShortLabel("Hello ")
.setLongLabel("Lable")
.build();
Intent addIntent = shortcutManager.createShortcutResultIntent(info);
shortcutManager.requestPinShortcut(info, PendingIntent.getBroadcast(context, 0, addIntent, 0).getIntentSender());
Toast.makeText(context, "supported_launcher", Toast.LENGTH_LONG).show();
} else {
// TODO: Maybe implement this for launchers without pin shortcut support?
// TODO: Should be the same with the fallback for Android < O
// for now just show unsupported
Toast.makeText(context, "unsupported_launcher", Toast.LENGTH_LONG).show();
}
}
Method 3: I am also used this code but not working
private fun addShourcut() {
if (ShortcutManagerCompat.isRequestPinShortcutSupported(applicationContext)) {
val shortcutInfo =
ShortcutInfoCompat.Builder(applicationContext, "#1")
.setIntent(
Intent(applicationContext, MainActivity::class.java).setAction(
Intent.ACTION_MAIN
)
) // !!! intent's action must be set on oreo
.setShortLabel("Test")
.setIcon(
IconCompat.createWithResource(
applicationContext,
R.mipmap.ic_launcher
)
)
.build()
ShortcutManagerCompat.requestPinShortcut(applicationContext, shortcutInfo, null)
} else {
Toast.makeText(
this#MainActivity, "launcher does not support short cut icon",Toast.LENGTH_LONG).show()
}
}
Please help me anyone i spent more time for this issue.
I found that desktop shortcut is not created in default launcher of vivo devices. When I changed default launcher to some other launcher It's let me create desktop shortcut. So as far I did R&d I found below solution it's not complete solution but you can redirect to allow Desktop shortcuts screen using below code.
val sintent = Intent()
sintent .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
sintent .component = ComponentName("com.bbk.launcher2", "com.bbk.launcher2.installshortcut.PurviewActivity")
activity.startActivity(sintent )
I tried to get result if user allowed or not but it's not work for all VIVO devices.
var uri = Uri.parse("content://com.bbk.launcher2.settings/favorites")
var query = activity.contentResolver.query(uri, null, " itemType = ?", arrayOf("30"), null);
if (query != null && query.count > 0) {
var idIndex = query.getColumnIndexOrThrow("_id");
var intentIndex = query.getColumnIndexOrThrow("intent");
var shortcutPermissionIndex = query.getColumnIndexOrThrow("shortcutPermission");
while (query.moveToNext()) {
val long = query.getLong(idIndex)
val intent = query.getString(intentIndex)
val shortcutPermission = query.getInt(shortcutPermissionIndex)
var unflattenFromString = ComponentName.unflattenFromString(intent)
Log.e("bhavin->", "initView: getShortcutPerBtn id=$long packageName= ${unflattenFromString!!.packageName} shortcutPermission= $shortcutPermission")
if (unflattenFromString!!.packageName == activity.packageName && shortcutPermission != 0 && shortcutPermission != 16){
val intent = Intent()
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.component = ComponentName("com.bbk.launcher2", "com.bbk.launcher2.installshortcut.PurviewActivity")
activity.startActivity(intent)
query.close()
return#ensureBackgroundThread
}
else{
Log.e("bhavin->","abcd")
}
}
query.close()
}
For more details you can check this I found this git
Note: I found exception some devices vivo 1902 and Z3
java.lang.SecurityException: Permission Denial: opening provider
com.bbk.launcher2.data.LauncherProvider from ProcessRecord{f8f30af
16137:com.qiutinghe.change/u0a172} (pid=16137, uid=10172) requires
com.bbk.launcher2.permission.READ_SETTINGS or
com.bbk.launcher2.permission.WRITE_SETTINGS
If any one found how to check desktop permission is allowed in Vivo devices please add into this answer.

Open WhatsApp chat window to a specific number without passing a message using kotlin

I need to open the WhatsApp chat window to a specific number without passing a message in the intent
I tried to remove the sendIntent.putExtra(Intent.EXTRA_TEXT, userText) but didn't help, when I send from the app it says
"Can't send empty message"
Here is the complete code
val sendIntent = Intent("android.intent.action.MAIN")
sendIntent.action = Intent.ACTION_SEND
sendIntent.setPackage("com.whatsapp")
sendIntent.type = "text/plain"
sendIntent.putExtra("jid", number + "#s.whatsapp.net")
sendIntent.putExtra(Intent.EXTRA_TEXT, userText)
startActivity(sendIntent)
You can use WhatsApp uri to open a specific whatsapp chat without using any message like this. Here num can be any valid number including country code like 911234567890
private fun openWhatsApp(num: String) {
val isAppInstalled = appInstalledOrNot("com.whatsapp")
if (isAppInstalled) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://api.whatsapp.com/send?phone=$num"))
startActivity(intent)
} else {
// WhatsApp not installed show toast or dialog
}
}
To check if WhatsApp is installed you can use this method
private fun appInstalledOrNot(uri: String): Boolean {
val pm = requireActivity().packageManager
return try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
}

Categories

Resources