我正在try 允许用户将我的应用程序中的图片分享到其他应用程序(如Whatsapp、Telegram、Gmail等).
我使用的是Android Studio,我的应用程序是用Kotlin 编写的.
以下是我的MainActivity.kt
条:
package com.example.example
import android.app.AlertDialog
import android.app.下载Manager
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.ContextMenu
import android.view.MenuItem
import android.view.View
import android.webkit.*
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.core.content.FileProvider
import java.io.File
import java.io.FileOutputStream
import java.net.URL
// OneSignal ID
const val ONESIGNAL_APP_ID = "REAL_KEY_HERE"
class MainActivity : ComponentActivity() {
private lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// OneSignal Initialization
// (Your existing OneSignal code here)
setContentView(R.layout.activity_main)
webView = findViewById(R.id.webView)
// Configure WebView settings
configureWebViewSettings()
// Set up WebViewClient
setWebViewClient()
// Set up WebChromeClient for handling file uploads
setWebChromeClient()
// Load the initial URL
webView.loadUrl("https://www.example.com/Directory/AppHome.php")
}
private fun configureWebViewSettings() {
val webSettings: WebSettings = webView.settings
// Enable JavaScript in the WebView
webSettings.javaScriptEnabled = true
// Enable caching
webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
// Enable hardware acceleration
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
} else {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
}
// Enable asynchronous loading
webSettings.blockNetworkImage = false
// Disable file access in the WebView
webSettings.allowFileAccess = false
// Disable insecure content (HTTP)
webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW
// Enable safe browsing only on devices with SDK version 27 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
webSettings.safeBrowsingEnabled = true
}
webSettings.setDisplayZoomControls(false)
// Disable metrics collection
webSettings.allowContentAccess = false
webSettings.allowFileAccess = false
webSettings.cacheMode = WebSettings.LOAD_NO_CACHE
}
private fun setWebViewClient() {
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
// Load the URL within the WebView
webView.loadUrl(request?.url.toString())
return true
}
}
}
private fun setWebChromeClient() {
registerForContextMenu(webView)
webView.webChromeClient = object : WebChromeClient() {
override fun onShowFileChooser(
webView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
// Handle file uploads if needed
return true
}
}
}
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
super.onCreateContextMenu(menu, v, menuInfo)
val hitTestResult = (v as WebView).hitTestResult
if (hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE ||
hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
) {
// If the user long-presses an image, show the context menu
menu?.add(0, 1, 0, "Save or share notification")
}
}
fun takeScreenshot(view: View): String? {
// Create a bitmap of the view
val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
view.draw(canvas)
// Save the bitmap to a file
val screenshotFile = File(Environment.getExternalStorageDirectory(), "screenshot.png")
try {
val fos = FileOutputStream(screenshotFile)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
fos.flush()
fos.close()
return screenshotFile.absolutePath
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
override fun onContextItemSelected(item: MenuItem): Boolean {
if (item.itemId == 1) {
val result = webView.hitTestResult
if (result.type == WebView.HitTestResult.IMAGE_TYPE ||
result.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
) {
val imageUrl = result.extra
if (!imageUrl.isNullOrEmpty()) {
// Show a dialog with options: 下载 or 外部共享
showImageOptionsDialog(imageUrl)
} else {
Toast.makeText(this, "No valid image URL found", Toast.LENGTH_SHORT).show()
}
}
return true
}
return super.onContextItemSelected(item)
}
private fun showImageOptionsDialog(imageUrl: String) {
val options = arrayOf("下载", "外部共享")
val builder = AlertDialog.Builder(this)
builder.setTitle("Choose an action")
.setItems(options) { dialog, which ->
when (which) {
0 -> downloadImage(imageUrl)
1 -> shareImageExternal(imageUrl)
}
dialog.dismiss()
}
val dialog = builder.create()
dialog.show()
}
private fun shareImageExternal(imageUrl: String) {
// 下载 and save the image to a file
val imageFilePath = downloadImageLocally(imageUrl)
// Check if the file was downloaded successfully
if (!imageFilePath.isNullOrBlank()) {
// Create a content URI from the file path
val imageFile = File(imageFilePath)
val imageUri = FileProvider.getUriForFile(
this,
applicationContext.packageName + ".provider",
imageFile
)
// Create an Intent to share the image
val shareIntent = Intent(Intent.ACTION_SEND)
shareIntent.type = "image/*"
shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri)
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
// Start the sharing activity
startActivity(Intent.createChooser(shareIntent, "Share Image External"))
} else {
Toast.makeText(this, "Failed to download and share the image", Toast.LENGTH_SHORT).show()
}
}
private fun downloadImage(imageUrl: String) {
val request = 下载Manager.Request(Uri.parse(imageUrl))
.setTitle("Image 下载")
.setDescription("下载ing")
.setNotificationVisibility(下载Manager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setAllowedNetworkTypes(下载Manager.Request.NETWORK_WIFI or 下载Manager.Request.NETWORK_MOBILE)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
"image.${getFileExtension(imageUrl)}"
)
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as 下载Manager
downloadManager.enqueue(request)
Toast.makeText(this, "下载ing IdentyAlert Notification", Toast.LENGTH_SHORT).show()
}
private fun downloadImageLocally(imageUrl: String): String? {
try {
val connection = URL(imageUrl).openConnection()
connection.connect()
val input = connection.getInputStream()
val imageFile = File.createTempFile("shared_image", ".png", cacheDir)
val output = FileOutputStream(imageFile)
val buffer = ByteArray(1024)
var bytesRead: Int
while (input.read(buffer).also { bytesRead = it } != -1) {
output.write(buffer, 0, bytesRead)
}
output.close()
input.close()
return imageFile.absolutePath
} catch (e: Exception) {
e.printStackTrace()
return null
}
}
private fun getFileExtension(url: String): String {
val mimeTypeMap = MimeTypeMap.getSingleton()
val extension = MimeTypeMap.getFileExtensionFromUrl(url)
return mimeTypeMap.getMimeTypeFromExtension(extension)?.split("/")?.get(1) ?: "jpg"
}
}
这是我的`Provider_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path
name="shared_images"
path="/"/>
</paths>
这是我的androidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/example_icon"
android:label="@string/app_name"
android:roundIcon="@drawable/identy_alert_icon"
android:supportsRtl="true"
android:theme="@style/Theme.example"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.example">
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" android:value="true" />
<meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
当用户按住图像时,用户有两个 Select :
- 下载
- 外部共享
下载选项运行完美. 共享选项显示错误:"无法下载和共享图像"
我已经try 了各种其他方法,但都没有成功.
你能帮我把这张照片分享到其他应用程序上吗?