Share Button In Compose - android

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

Related

Android Package Manager install not showing

I'm trying to build an auto updater via github. The app so far detects new available versions and downloads the apk file. I however cannot get it to install the apk file.
There are no crashes or Log messages indicating an error. The install dialog just does not show up.
This is my code:
fun downloadAndInstall(link: Uri, fileName: String){
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri = link
val request = DownloadManager.Request(downloadUri)
request.setMimeType(MIME_TYPE)
val destination = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/" + fileName
val destinationUri = Uri.parse("file://$destination")
request.setDestinationUri(destinationUri)
fun showInstallOption(destination: String) {
val onComplete = object : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent
) {
val contentUri = FileProvider.getUriForFile(
context,
BuildConfig.APPLICATION_ID + ".provider",
File(destination)
)
val installer = context.packageManager.packageInstaller
val resolver = context.contentResolver
resolver.openInputStream(contentUri)?.use { apkStream ->
val length =
DocumentFile.fromSingleUri(context, contentUri)?.length() ?: -1
val params =
PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId = installer.createSession(params)
val session = installer.openSession(sessionId)
session.openWrite("INSTALL", 0, length).use { sessionStream ->
apkStream.copyTo(sessionStream)
session.fsync(sessionStream)
}
val intent = Intent(context, InstallReceiver::class.java)
intent.action = "com.blazecode.tsviewer.util.updater.SESSION_API_PACKAGE_INSTALLED"
val pi = PendingIntent.getBroadcast(
context,
3,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
session.commit(pi.intentSender)
session.close()
}
Toast.makeText(context, "done", Toast.LENGTH_LONG).show()
}
}
context.registerReceiver(onComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
}
showInstallOption(destination)
downloadManager.enqueue(request)
Toast.makeText(context, context.getString(R.string.downloading), Toast.LENGTH_LONG).show()
}
I tested this on Android 13 and 8, both with the same result. Android 13 is a physical device. Android 8 is an emulator.

How to hardcode file type while creating it using ActivityResultContracts.CreateDocument()?

I'm creating file using
private val getContent = registerForActivityResult(ActivityResultContracts.CreateDocument()) { uri ->
uri?.let { writeToFile(requireActivity(), it) }
}
and then launch it:
getContent.launch("file.csv")
so when i'm in launcher i can rename file before saving and also change file type which is not what i expect. So can i let user change name but hardcore this type?
private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult())
{ result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
// make action
}
}
private fun createFile() {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "image/png"
intent.putExtra(Intent.EXTRA_TITLE, "AA.png")
startForResult.launch(intent)
}

How do I start an Intent inside a Compose function's button click

I want to redirect the user to another activity that opens a internet url. On button click.
Here is my code so far
Button(onClick = {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"))
// Here is some code that starts the activity
}) {
Text(text="APPLY HACK")
}
You can use something like:
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"))
val context = LocalContext.current
Button(onClick = {
startActivity(context, intent, null) }
) {
Text("BUTTON")
}
val context = LocalContext.current
Button(onClick = {
context.startActivity(Intent(Intent.ACTION_VIEW,Uri.parse("http://www.google.com"))) }
) {
Text("Click here")
}

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")
}
}

why Intent.EXTRA_INITIAL_INTENTS not working in android 10

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

Categories

Resources