文章目录
下载PDF后的responseBody写入本地
val responseBody = downLoadResponseBodyBean.respone
logE("收到responseBody.length == ${responseBody?.contentLength()}")
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
thread {
responseBody?.let { writePDF(it) }
}.start()
} else{
GlobalScope.launch {
responseBody?.let { writePDFQ(it) }
}
}
Android10以下写入
fun writePDF(body: ResponseBody): Boolean {
var length = 0L
var result = 0
return try {
val files = File(PDF_PATH)
if (!files.exists()) {
files.mkdirs()
}
val futureStudioIconFile = File(PDF_PATH_NAME)
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
try {
val fileReader = ByteArray(1024)
val fileSize: Long = body.contentLength()
inputStream = body.byteStream()
outputStream = FileOutputStream(futureStudioIconFile)
while (true) {
val read: Int = inputStream.read(fileReader)
if (read == -1) {
break
}
outputStream.write(fileReader,0,read)
length += read
result = (100*length/fileSize).toInt()
if(result>0){
logE("监听PDF写入文件进度 : ${result}%")
ownerDashBoardModel.downLoadPDFProgress.postValue(result)
}
}
outputStream.flush()
true
} catch (e: IOException) {
logE("网络错误${e.printStackTrace()}")
false
} finally {
try {
inputStream!!.close()
outputStream!!.close()
} catch(e: Exception) {
e.printStackTrace()
}
}
} catch (e: IOException) {
logE(e.message)
false
}
}
android 10 以上写入
@RequiresApi(Build.VERSION_CODES.Q)
private suspend fun writePDFQ(responseBody: ResponseBody) {
var length = 0L
withContext(Dispatchers.IO){
var result = 0
val fileSize: Long = responseBody.contentLength()
logE("文件大小:$fileSize")
try {
val inputStream = responseBody.byteStream()
val bis = BufferedInputStream(inputStream)
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
values.put(MediaStore.Downloads.MIME_TYPE, "application/pdf")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
var uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
if (uri != null) {
val outputStream = contentResolver.openOutputStream(uri)
if (outputStream != null) {
val bos = BufferedOutputStream(outputStream)
val buffer = ByteArray(1024)
var bytes = bis.read(buffer)
while (bytes >= 0) {
bos.write(buffer, 0 , bytes)
bos.flush()
bytes = bis.read(buffer)
length += bytes
result = (101*length/fileSize).toInt()
if(result in 1..100){
logE("Q监听PDF写入文件进度 : ${result}%")
ownerDashBoardModel.downLoadPDFProgress.postValue(result)
}
}
bos.close()
}
}else{
Toast.makeText(context, "$fileName 写入异常", Toast.LENGTH_SHORT).show()
}
bis.close()
}catch (e: Exception) {
e.printStackTrace()
}
}
}
- Android10以下写入SD卡根目录,可自己创建文件夹
- Android10以及以上上放入公共目录 Download目录下,而且是在根目录下,不然隐式调用第三方APP打开文件的时候会有权限问题 Permission denied
使用腾讯tbs内核在webview中直接打开本地PDF文件
<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
<RelativeLayout
android:id="@+id/rl_pdf"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.beans.base.widget.TBSWebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.beans.base.widget.TBSWebView>
</RelativeLayout>
直接打开本地PDF文件
var tbsReaderView:TbsReaderView? = null
private fun openPDF() {
var bundle = Bundle()
if(isAndroidQ()){
bundle.putString("filePath", "/storage/emulated/0/Download/wey.pdf")
bundle.putString("tempPath", context.cacheDir?.path+"/wey.pdf")
}else{
bundle.putString("filePath", getPdfPath())
bundle.putString("tempPath", Environment.getExternalStorageDirectory().path)
}
var result = tbsReaderView!!.preOpen(parseFormat(parseName()),false)
if (result){
tbsReaderView!!.openFile(bundle)
}else{
QbSdk.openFileReader(this,"/storage/emulated/0/Download/wey.pdf",null, ValueCallback {
logE("x5打卡文件PDF $it")
})
}
}
private fun parseFormat( fileName:String):String{
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
private fun parseName():String{
return PDF_PATH_NAME.substring(PDF_PATH_NAME.lastIndexOf("/")+1)
}
隐式调用第三方应用打开PDF
val PDF_PATH: String = Environment.getExternalStorageDirectory().getPath().toString() + "/wey/"
val PDF_PATH_NAME: String = "${PDF_PATH}wey.pdf"
var file :File
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
file= File(PDF_PATH_NAME)
}else{
file = File("/storage/emulated/0/Download/", fileName)
}
if(!file.exists()) {
ToastUtils.s(this,"文件找不到")
return@OnClickListener
}
val intent = Intent(Intent.ACTION_VIEW)
var uri :Uri
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ){
uri = Uri.parse(PDF_PATH_NAME)
if( Build.VERSION.SDK_INT >=Build.VERSION_CODES.Q){
uri = Uri.parse(PDF_PATH_Q_NAME)
}
}else{
uri = Uri.fromFile(file)
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setDataAndType(uri, "application/pdf")
var componentName:ComponentName = intent.resolveActivity(packageManager)
if(componentName == null){
ToastUtils.s(this,"没有可用的其他程序")
return@OnClickListener
}else{
logE("跳转程序 $componentName")
}
try {
startActivityForResult(intent,PDF_JUMP_CODE)
} catch(e: ActivityNotFoundException) {
Log.e("URLSpan","Activity was not found for intent, $intent")
}
override fun onDestroy() {
super.onDestroy()
mBinding.webView.clearCache(true)
mBinding.webView.clearFormData()
mBinding.webView.destroy()
tbsReaderView!!.onStop()
}