package com.jld.vod.view import android.app.ProgressDialog import android.content.Context import android.os.Handler import android.os.Looper import android.os.Message import android.widget.Toast import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.observe import com.google.gson.Gson import com.jld.vod.R import com.jld.vod.base.BaseActivity import com.jld.vod.config.Config import com.jld.vod.model.bean.BaseBean import com.jld.vod.model.bean.ResultBean import com.jld.vod.model.event.UsbStatusChangeEvent import com.jld.vod.utils.HttpFileUtils import com.jld.vod.utils.LogUtils import com.jld.vod.utils.http.HttpFileUtil import com.jld.vod.utils.http.ProgressFragmentRequestBody import com.jld.vod.utils.http.ProgressListener import com.jld.vod.viewmodel.MainViewModel import com.jld.vod.viewmodel.PostFileViewModel import okhttp3.Callback import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import java.io.* /** * @author ZhaoFuXin * @Email:18276061387@163.com * @description: * @date :2020/7/27 11:09 */ class PostFileActivity : BaseActivity() { private var strFilePath: String? = null private var gson: Gson? = null private lateinit var postFileViewModel: PostFileViewModel private lateinit var mainViewModel: MainViewModel private var progressdialog: ProgressDialog? = null private var totalitem = 0//数据大小 private var lenitem = 1//当前上传数据下标 private var flag = true private var context: Context? = null private lateinit var myHandler: Handler private var progressitem:Int = 0 private val mHandler = object : Handler() { override fun handleMessage(msg: Message) { super.handleMessage(msg) when (msg.what) { 0 -> { val id: Int = msg.arg1 val file = msg.obj as String // LogUtils.logD("id===$id====file==$file") progressdialog!!.setTitle("Uploading Movie ( $lenitem/$totalitem )") progressdialog!!.progress = id progressdialog!!.setMessage(file) progressdialog!!.setCancelable(false) progressdialog!!.setCanceledOnTouchOutside(false) progressdialog!!.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) progressdialog!!.show() if (id == 100) { progressdialog!!.dismiss() } } 1 -> { val id: Int = msg.arg1 val file = msg.obj as String progressdialog!!.setTitle("Uploading Music ( $lenitem/$totalitem )") progressdialog!!.progress = id progressdialog!!.setMessage(file) progressdialog!!.setCancelable(false) progressdialog!!.setCanceledOnTouchOutside(false) progressdialog!!.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) progressdialog!!.show() if (id == 100) { progressdialog!!.dismiss() } } 2 -> { val id: Int = msg.arg1 val file = msg.obj as String progressdialog!!.setTitle("Uploading Game ( $lenitem/$totalitem )") progressdialog!!.progress = id progressdialog!!.setMessage(file) progressdialog!!.setCancelable(false) progressdialog!!.setCanceledOnTouchOutside(false) progressdialog!!.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) progressdialog!!.show() if (id == 100) { progressdialog!!.dismiss() } } 3 -> { val id: Int = msg.arg1 val file = msg.obj as String progressdialog!!.setTitle("Uploading Ads ( $lenitem/$totalitem )") progressdialog!!.progress = id progressdialog!!.setMessage(file) progressdialog!!.setCancelable(false) progressdialog!!.setCanceledOnTouchOutside(false) progressdialog!!.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) progressdialog!!.show() if (id == 100) { progressdialog!!.dismiss() } } } } } override fun getLayoutId(): Int { return R.layout.activity_postfile } override fun initView() { super.initView() context = this progressdialog = ProgressDialog(this@PostFileActivity) // if (myHandler==null){ // myHandler = new MyHandler(); // } val WorkerThread = WorkerThread() WorkerThread.start() } override fun initData() { super.initData() //初始化gson gson = Gson() //u盘路径 val mIntent = intent strFilePath = mIntent.getStringExtra("path") //接收U盘广播值 EventBus.getDefault().register(this) //初始化viewmodel postFileViewModel = ViewModelProvider.AndroidViewModelFactory(application) .create(PostFileViewModel::class.java) //获取未上传电影列表 postFileViewModel.findResByNotUploadedmovie() //初始化电影列表 initMovieList() //初始化音乐列表 initMusicList() //初始化游戏列表 initGameList() //初始化广告列表 initAdvertList() } /** * 初始化电影列表 */ private fun initMovieList() { postFileViewModel.findResByNotUploadedmovieliveData.observe(this) { res -> LogUtils.logD("initMovieList" + res.data) when (res?.code) { BaseBean.SUCCESS -> { finishLoading() if (res.data!!.size != 0) { // for ((index, data) in res.data.withIndex()) { // val file = File(strFilePath, data.movieId.toString() + ".mp4") // if (file.exists()) { // totalitem++ // } // } for ((index, data) in res.data.withIndex()) { val file = File(strFilePath, data.movieId.toString() + ".mp4") val mid = data.mid val resId = data.movieId if (file.exists()) { //上传电影 postFileMovie(file, mid, resId) // postFileMovieByFragmentUpload(file, mid, resId) } else { if (flag) { flag = false postFileViewModel.findResByNotUploadedmusic()//继续获取未上传音乐列表 } } } } else { postFileViewModel.findResByNotUploadedmusic()//继续获取未上传音乐列表 } } BaseBean.ERROR -> { finishLoading() Toast.makeText(this, res.message, Toast.LENGTH_SHORT).show() } BaseBean.LOADING -> showLoading() } } } /** * 初始化音乐列表 */ private fun initMusicList() { postFileViewModel.findResByNotUploadedmusicliveData.observe(this) { res -> when (res?.code) { BaseBean.SUCCESS -> { flag = true finishLoading() if (res.data!!.size != 0) { for ((index, data) in res.data.withIndex()) { val file = File(strFilePath, data.musicId.toString() + ".mp3") val mid = data.mid val resId = data.musicId if (file.exists()) { //上传音乐 postFileMusic(file, mid, resId) } else { if (flag) { flag = false postFileViewModel.findResByNotUploadedadvert()//继续获取未上传广告列表 } } } } else { postFileViewModel.findResByNotUploadedadvert()//继续获取未上传广告列表 } } BaseBean.ERROR -> { finishLoading() Toast.makeText(this, res.message, Toast.LENGTH_SHORT).show() } BaseBean.LOADING -> showLoading() } } } /** * 初始化广告列表 */ private fun initAdvertList() { postFileViewModel.findResByNotUploadedadvertliveData.observe(this) { res -> LogUtils.logD("initAdvertList" + res.data) when (res?.code) { BaseBean.SUCCESS -> { flag = true finishLoading() if (res.data!!.size != 0) { for ((index, data) in res.data.withIndex()) { val file = File(strFilePath, data.aid.toString() + ".mp4") val resId = data.aid if (file.exists()) { //上传广告 postFileAdvert(file, 123456L, resId) } else { if (flag) { flag = false postFileViewModel.findResByNotUploadedgame()//继续获取未上传游戏列表 } } } } else { postFileViewModel.findResByNotUploadedgame()//继续获取未上传游戏列表 } } BaseBean.ERROR -> { finishLoading() Toast.makeText(this, res.message, Toast.LENGTH_SHORT).show() } BaseBean.LOADING -> showLoading() } } } /** * 初始化游戏列表 */ private fun initGameList() { //监听游戏列表 postFileViewModel.findResByNotUploadedgameliveData.observe(this) { res -> // LogUtils.logD("game"+res) when (res?.code) { BaseBean.SUCCESS -> { finishLoading() if (res.data!!.size != 0) { for ((index, data) in res.data.withIndex()) { val file = File(strFilePath, data.gid.toString() + ".apk") val mid = data.mid val resId = data.gid if (file.exists()) { //上传游戏 postFileGame(file, mid, resId) } } } else { LogUtils.logD("上传数据为空") } } BaseBean.ERROR -> { finishLoading() Toast.makeText(this, res.message, Toast.LENGTH_SHORT).show() } BaseBean.LOADING -> showLoading() } } } /** * 上传游戏 */ private fun postFileGame(file: File, mid: Long, resId: Long) { totalitem++ HttpFileUtil.getInstance().postFile(this, Config.ApiBaseUrl + "/game/upload", object : ProgressListener { override fun onProgress(currentBytes: Long, contentLength: Long, done: Boolean) { // Log.i(TAG, "file="+file.getName()+"id="+id+"currentBytes==" + currentBytes + "==contentLength==" + contentLength + "==done==" + done); val progress = (currentBytes * 100 / contentLength).toInt() if (done == true) { lenitem++ if (lenitem == totalitem) { //数据下标重置 lenitem = 1 totalitem = 0 //postFileViewModel.findResByNotUploadedgame()//继续获取未上传游戏列表 } } val msg: Message = mHandler.obtainMessage() msg.arg1 = progress msg.what = 2 msg.obj = file.name mHandler.sendMessage(msg) } }, object : Callback { override fun onFailure(call: okhttp3.Call, e: IOException) { LogUtils.logE(e.toString()) } @Throws(IOException::class) override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) { val result = response.body!!.string() LogUtils.logD(result.toString()) } }, file, mid, resId ) } /** * 上传音乐 */ private fun postFileMusic(file: File, mid: Long, resId: Long) { totalitem++ HttpFileUtil.getInstance().postFile(this, Config.ApiBaseUrl + "/music/upload", object : ProgressListener { override fun onProgress(currentBytes: Long, contentLength: Long, done: Boolean) { // Log.i(TAG, "file="+file.getName()+"id="+id+"currentBytes==" + currentBytes + "==contentLength==" + contentLength + "==done==" + done); val progress = (currentBytes * 100 / contentLength).toInt() if (done == true) { lenitem++ if (lenitem == totalitem) { //数据下标重置 lenitem = 1 totalitem = 0 postFileViewModel.findResByNotUploadedadvert()//继续获取未上传广告列表 } } val msg: Message = mHandler.obtainMessage() msg.arg1 = progress msg.what = 1 msg.obj = file.name mHandler.sendMessage(msg) } }, object : Callback { override fun onFailure(call: okhttp3.Call, e: IOException) { LogUtils.logE(e.toString()) } @Throws(IOException::class) override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) { val result = response.body!!.string() LogUtils.logD(result.toString()) } }, file, mid, resId ) } /** * 上传音乐 */ private fun postFileAdvert(file: File, mid: Long, resId: Long) { totalitem++ HttpFileUtil.getInstance().postFile(this, Config.ApiBaseUrl + "/advert/upload", object : ProgressListener { override fun onProgress(currentBytes: Long, contentLength: Long, done: Boolean) { // Log.i(TAG, "file="+file.getName()+"id="+id+"currentBytes==" + currentBytes + "==contentLength==" + contentLength + "==done==" + done); val progress = (currentBytes * 100 / contentLength).toInt() if (done == true) { lenitem++ if (lenitem == totalitem) { //数据下标重置 lenitem = 1 totalitem = 0 postFileViewModel.findResByNotUploadedgame()//继续获取未上传游戏列表 } } val msg: Message = mHandler.obtainMessage() msg.arg1 = progress msg.what = 3 msg.obj = file.name mHandler.sendMessage(msg) } }, object : Callback { override fun onFailure(call: okhttp3.Call, e: IOException) { LogUtils.logE(e.toString()) } @Throws(IOException::class) override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) { val result = response.body!!.string() LogUtils.logD(result.toString()) } }, file, mid, resId ) } /** * 上传电影 */ private fun postFileMovie(file: File, mid: Long, resId: Long) { totalitem++ HttpFileUtil.getInstance().postFile(this, Config.ApiBaseUrl + "/movie/upload", object : ProgressListener { override fun onProgress(currentBytes: Long, contentLength: Long, done: Boolean) { // Log.i("PostFile====", "file="+file.getName()+"currentBytes==" + currentBytes + "==contentLength==" + contentLength + "==done==" + done); val progress = (currentBytes * 100 / contentLength).toInt() if (done) { if (lenitem == totalitem) { //数据下标重置 lenitem = 1 totalitem = 0 postFileViewModel.findResByNotUploadedmusic()//继续获取未上传音乐列表 } lenitem++ } if (progress > progressitem) { progressitem = progress val msg: Message = mHandler.obtainMessage() msg.arg1 = progress msg.what = 0 msg.obj = file.name mHandler.sendMessage(msg) if (progress >= 100) { progressitem = 0 } } } }, object : Callback { override fun onFailure(call: okhttp3.Call, e: IOException) { LogUtils.logE(e.toString()) } @Throws(IOException::class) override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) { val result = response.body!!.string() LogUtils.logD(result.toString()) } }, file, mid, resId ) } /** * 电影上传分片 */ private fun postFileMovieByFragmentUpload(file: File, mid: Long, resId: Long) { LogUtils.logD("进入分片上传") // Thread { // totalitem++ // }.start() //// //触发第一次UI var msg: Message = myHandler.obtainMessage() msg.arg1 = 0//当前进度 按分片进度进行 msg.what = 123 msg.obj = file.name myHandler.sendMessage(msg) //将数据分片 var s1 = file.name //文件名称 //计算文件总分片大小 var length = file.length() //当前文件大小 var total = 0 //总分片大小 var chunkSize = 100 * 1024 * 1024 //分片大小 最好是long型 total = if (length % chunkSize == 0L) { (length / chunkSize).toInt() } else { (length / chunkSize).toInt() + 1 } LogUtils.logD("当前分片数大小:$total") var tmp = true //读取进度结束符 var index = 0 //获取缓存地址 // val cachePath = cacheDir var uploadIndex = 0 //当前已上传的分片 while (tmp) {//这里true一直在循环就阻塞了 //判断当前已分个数 和已上传分片个数差值 现在只允许4个同时上传 if ((index - uploadIndex) < 1) { //(index - uploadIndex) < 1 // Thread(Runnable { var offset = chunkSize * index * 1L var block: ByteArray? = getBlock(offset, file, chunkSize) if (block != null) { var filePath = cacheDir.absolutePath + "/" + s1 + "_" + index + ".tmp" //缓存目录 外部自定义 var out: OutputStream = FileOutputStream(filePath) var inputStream: InputStream = ByteArrayInputStream(block) var buff = ByteArray(1024) var len = 0 while (inputStream.read(buff).also { len = it } != -1) { out.write(buff, 0, len) } inputStream.close() out.close() LogUtils.logD("开始上传" + filePath) HttpFileUtils.postFileByFragmentUpload( Config.ApiBaseUrl + "/movie/uploadFile", object : ProgressListener { override fun onProgress( currentBytes: Long, contentLength: Long, done: Boolean ) { //UI进度展示问题 //LogUtils.logD("当前进度:currentBytes=$currentBytes====contentLength=$contentLength===" + done) // var msg: Message = myHandler.obtainMessage() // msg.arg1 = progress//当前进度 按分片进度进行 // msg.what = 123 // msg.obj = file.name // myHandler.sendMessage(msg) //一会在处理... } }, object : Callback { override fun onFailure(call: okhttp3.Call, e: IOException) { LogUtils.logE(e.toString()) } @Throws(IOException::class) override fun onResponse( call: okhttp3.Call, response: okhttp3.Response ) { val result = response.body!!.string() // LogUtils.logD(result.toString()) val resultData = gson!!.fromJson(result, ResultBean::class.java) //设置当前已完成的片数 if (resultData.flag) { //估计会有线程安全问题 uploadIndex++//计数已上传个数 File(filePath).delete()//删除缓存文件 //根据返回值判断是否上传完成 if (resultData.message == "1") { // 通知 var msg: Message = myHandler.obtainMessage() msg.what = 4 myHandler.sendMessage(msg) } // UI更新 var msg: Message = myHandler.obtainMessage() msg.arg1 = (uploadIndex * 100 / total)//当前进度 按分片进度进行 msg.what = 123 msg.obj = file.name myHandler.sendMessage(msg) LogUtils.logD("当前上传进度uploadIndex=$uploadIndex==total=$total:" + (uploadIndex * 100 / total)) } } }, File(filePath), total, chunkSize * 1L, "111", s1, index, resId, mid ) index++ } else { tmp = false } } } } inner class WorkerThread : Thread() { override fun run() { super.run() Looper.prepare() myHandler = object : Handler() { override fun handleMessage(msg: Message) { super.handleMessage(msg) when (msg.what) { 123 -> { val id: Int = msg.arg1 val file = msg.obj as String //LogUtils.logD("id===$id====file==$file lenitem==$lenitem====totalitem==$totalitem ") progressdialog!!.setTitle("Uploading Movie ( $lenitem/$totalitem )") progressdialog!!.progress = id progressdialog!!.setMessage(file) progressdialog!!.setCancelable(false) progressdialog!!.setCanceledOnTouchOutside(false) progressdialog!!.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) progressdialog!!.show() if (id == 100) { progressdialog!!.dismiss() } } 4->{ lenitem++ if (lenitem == totalitem) { //数据下标重置 lenitem = 1 totalitem = 0 postFileViewModel.findResByNotUploadedmusic()//继续获取未上传音乐列表 } } 5->{ lenitem++ } } } } Looper.loop() } } /** * 文件分块工具 * * @param offset 起始偏移位置 * @param file 文件 * @param blockSize 分块大小 * @return 分块数据 */ private fun getBlock(offset: Long, file: File?, blockSize: Int): ByteArray? { val result = ByteArray(blockSize) var accessFile: RandomAccessFile? = null try { accessFile = RandomAccessFile(file, "r") accessFile.seek(offset) val readSize: Int = accessFile.read(result) return if (readSize == -1) { null } else if (readSize == blockSize) { result } else { val tmpByte = ByteArray(readSize) System.arraycopy(result, 0, tmpByte, 0, readSize) tmpByte } } catch (e: IOException) { e.printStackTrace() } finally { if (accessFile != null) { try { accessFile.close() } catch (e1: IOException) { } } } return null } override fun onDestroy() { super.onDestroy() progressdialog!!.dismiss() if (EventBus.getDefault().isRegistered(this)) { EventBus.getDefault().unregister(this) } } /** * 广播传来值处理 * @param event */ @Subscribe(threadMode = ThreadMode.MAIN) fun onNetworkChangeEvent(event: UsbStatusChangeEvent) { if (event.isConnected) { finish() } } }