从Android推送通知中打开最近下载的PDF

问题描述 投票:0回答:1

我正在提示用户将PDF文件下载到设备存储中,然后发送一条通知,该通知将使用在Uri方法中返回的相同OnActivityResult()打开该文件。但是似乎新的Intent无法打开此Uri,当我单击通知时什么也没有发生。这是代码:

private fun firePushNotification() {
    val intent: Intent

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent = Intent(Intent.ACTION_VIEW).apply {
            data = uri // From OnActivityResult()
            type = "application/pdf"
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
    } else {
        intent = Intent(Intent.ACTION_VIEW).apply {
            data = uri
            type = "application/pdf"
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
    }

    // Push logic
    val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
    val builder = NotificationCompat.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.app_logo)
            .setContentTitle("Download concluído")
            .setContentText("Abrir PDF")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(CHANNEL_ID, "Channel 1",
            NotificationManager.IMPORTANCE_DEFAULT).apply {
            description = ""
        }
        // Register the channel with the system
        val notificationManager: NotificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }

    NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build())
}

我还尝试使用带有此代码的File创建一个uri

private fun firePushNotification() {
    val intent: Intent

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        val input = context.contentResolver.openInputStream(uri)
        val file = File(Environment.getDownloadCacheDirectory().absolutePath, pdfName)
        val output = FileOutputStream(file)
        copyStream(input!!, output)
        intent = Intent(Intent.ACTION_VIEW).apply {
            data = FileProvider.getUriForFile(context, context.packageName + ".provider", file)
            type = "application/pdf"
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
    } else {
        intent = Intent(Intent.ACTION_VIEW).apply {
            data = uri
            type = "application/pdf"
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
    }

    // Push logic ...
}

copystream()方法:

@Throws(IOException::class)
fun copyStream(inp: InputStream, out: OutputStream) {
    val buffer = ByteArray(1024)
    var read: Int
    while (inp.read(buffer).also { read = it } != -1) {
        out.write(buffer, 0, read)
    }
}

但出现错误:

Caused by: java.io.FileNotFoundException: /data/cache/my_pdf.pdf (Permission denied)

是否有另一种方式可以使用用户输入提供的uri打开最近下载的文件?

android file kotlin
1个回答
0
投票

经过测试的智能手机操作系统版本为Android10吗?从Android10开始,存储访问已更改,因此您无法访问公共存储端。

您需要对其进行修改以将其存储在私有存储中,例如,

val file = File(Environment.getDownloadCacheDirectory().absolutePath, pdfName)

结果路径:/ data / cache

而不是,

val file = File(context.cacheDir.absolutePath, pdfName)

结果路径:/ data / user / 0 / {yourPackage} / cache

Google进行此更改的原因是为了防止不必要的容量即使由于不加选择地删除了应用程序也无法填充使用公共存储。

但是,在应用程序的AndroidManifest.xml中将requestLegacyExternalStorage属性设置为true不会应用范围存储策略,如下所示:

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting Android Q. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>
© www.soinside.com 2019 - 2024. All rights reserved.