4 changed files with 154 additions and 14 deletions
@ -1,58 +1,196 @@ |
|||||
package com.wuliang.xapkinstaller |
package com.wuliang.xapkinstaller |
||||
|
|
||||
import android.Manifest |
import android.Manifest |
||||
import android.content.Context |
import android.annotation.SuppressLint |
||||
|
import android.app.ProgressDialog |
||||
|
import android.content.Intent |
||||
|
import android.content.pm.PackageManager |
||||
import android.os.Build |
import android.os.Build |
||||
import android.os.Bundle |
import android.os.Bundle |
||||
|
import android.os.Environment |
||||
|
import android.provider.Settings |
||||
import android.widget.TextView |
import android.widget.TextView |
||||
|
import android.widget.Toast |
||||
|
import androidx.appcompat.app.AlertDialog |
||||
import androidx.appcompat.app.AppCompatActivity |
import androidx.appcompat.app.AppCompatActivity |
||||
import androidx.core.app.ActivityCompat |
import androidx.core.app.ActivityCompat |
||||
|
import com.liulishuo.okdownload.DownloadListener |
||||
|
import com.liulishuo.okdownload.DownloadTask |
||||
|
import com.liulishuo.okdownload.core.cause.EndCause |
||||
|
import com.liulishuo.okdownload.core.cause.ResumeFailedCause |
||||
|
import com.liulishuo.okdownload.core.listener.DownloadListener1 |
||||
|
import com.liulishuo.okdownload.core.listener.DownloadListener2 |
||||
|
import com.liulishuo.okdownload.core.listener.assist.Listener1Assist |
||||
import com.wuliang.lib.createXapkInstaller |
import com.wuliang.lib.createXapkInstaller |
||||
|
import java.io.File |
||||
|
import java.lang.Exception |
||||
import java.util.concurrent.ExecutorService |
import java.util.concurrent.ExecutorService |
||||
import java.util.concurrent.Executors |
import java.util.concurrent.Executors |
||||
|
|
||||
class MainActivity : AppCompatActivity() { |
private const val PERMISSION_REQUEST_CODE = 99 |
||||
|
private const val ACTION_MANAGE_UNKNOWN_APP_SOURCES_REQUEST_CODE = 120 |
||||
|
|
||||
private lateinit var installExecutor: ExecutorService |
class MainActivity : AppCompatActivity() { |
||||
|
|
||||
override fun onCreate(savedInstanceState: Bundle?) { |
override fun onCreate(savedInstanceState: Bundle?) { |
||||
super.onCreate(savedInstanceState) |
super.onCreate(savedInstanceState) |
||||
setContentView(R.layout.activity_main) |
setContentView(R.layout.activity_main) |
||||
|
|
||||
findViewById<TextView>(R.id.install_tv).setOnClickListener { |
findViewById<TextView>(R.id.install_tv).setOnClickListener { |
||||
install() |
checkAndInstall() |
||||
} |
} |
||||
|
} |
||||
|
|
||||
|
private fun checkAndInstall() { |
||||
if (Build.VERSION.SDK_INT >= 26) {//8.0 |
if (Build.VERSION.SDK_INT >= 26) {//8.0 |
||||
//来判断应用是否有权限安装apk |
//来判断应用是否有权限安装apk |
||||
val installAllowed = packageManager.canRequestPackageInstalls() |
val installAllowed = packageManager.canRequestPackageInstalls() |
||||
//有权限 |
//有权限 |
||||
if (installAllowed) { |
if (installAllowed) { |
||||
//安装apk |
//安装apk |
||||
|
install() |
||||
} else { |
} else { |
||||
//无权限 申请权限 |
//无权限 申请权限 |
||||
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.REQUEST_INSTALL_PACKAGES, Manifest.permission.WRITE_EXTERNAL_STORAGE), |
ActivityCompat.requestPermissions( |
||||
99) |
this, |
||||
|
arrayOf( |
||||
|
Manifest.permission.REQUEST_INSTALL_PACKAGES, |
||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE |
||||
|
), |
||||
|
PERMISSION_REQUEST_CODE |
||||
|
) |
||||
} |
} |
||||
} else {//8.0以下 |
} else {//8.0以下 |
||||
//安装apk |
//安装apk |
||||
|
install() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
override fun onRequestPermissionsResult( |
||||
|
requestCode: Int, |
||||
|
permissions: Array<out String>, |
||||
|
grantResults: IntArray |
||||
|
) { |
||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults) |
||||
|
|
||||
|
if (requestCode != PERMISSION_REQUEST_CODE) |
||||
|
return |
||||
|
|
||||
|
grantResults.forEachIndexed { index, grantResult -> |
||||
|
if (grantResult != PackageManager.PERMISSION_GRANTED) { |
||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
||||
|
if (Manifest.permission.REQUEST_INSTALL_PACKAGES == permissions[index]) { |
||||
|
//引导用户去手动开启权限 |
||||
|
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) |
||||
|
startActivityForResult( |
||||
|
intent, |
||||
|
ACTION_MANAGE_UNKNOWN_APP_SOURCES_REQUEST_CODE |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
Toast.makeText(this, "权限不足!", Toast.LENGTH_SHORT).show(); |
||||
|
return |
||||
|
} |
||||
} |
} |
||||
|
|
||||
|
install() |
||||
|
} |
||||
|
|
||||
|
@SuppressLint("NewApi") |
||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
||||
|
super.onActivityResult(requestCode, resultCode, data) |
||||
|
|
||||
|
if (requestCode == ACTION_MANAGE_UNKNOWN_APP_SOURCES_REQUEST_CODE) { |
||||
|
if (packageManager.canRequestPackageInstalls()) { |
||||
|
install() |
||||
|
} else { |
||||
|
Toast.makeText(this, "权限不足!", Toast.LENGTH_SHORT).show(); |
||||
|
} |
||||
|
} |
||||
} |
} |
||||
|
|
||||
private fun install() { |
private fun install() { |
||||
|
downloadXapkAndInstall() |
||||
|
} |
||||
|
|
||||
|
private fun downloadXapkAndInstall() { |
||||
|
val outputFileDirectory = File( |
||||
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + |
||||
|
File.separator + "xapk" |
||||
|
) |
||||
|
if (!outputFileDirectory.exists()) |
||||
|
outputFileDirectory.mkdir() |
||||
|
|
||||
installExecutor = Executors.newSingleThreadExecutor() |
val outputFileName = "LEGO_CITY.xapk" |
||||
installExecutor.execute { |
val outputFile = File(outputFileDirectory.absolutePath + File.separator + outputFileName) |
||||
createXapkInstaller(getXapkFilePath())?.installXapk(this@MainActivity) |
|
||||
|
if (outputFile.exists()) { |
||||
|
doInstall(outputFile.absolutePath) |
||||
} |
} |
||||
|
|
||||
|
//TODO this is xapk download url |
||||
|
val downloadUrl = "" |
||||
|
|
||||
|
val task = DownloadTask.Builder( |
||||
|
downloadUrl, |
||||
|
outputFileDirectory |
||||
|
) |
||||
|
.setFilename(outputFileName) |
||||
|
.build() |
||||
|
|
||||
|
val dialog = ProgressDialog(this) |
||||
|
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL) |
||||
|
dialog.isIndeterminate = false |
||||
|
dialog.setCancelable(false) |
||||
|
dialog.max = 100 |
||||
|
dialog.setTitle("正在下载中...") |
||||
|
|
||||
|
task.enqueue(object : DownloadListener1() { |
||||
|
override fun taskStart(task: DownloadTask, model: Listener1Assist.Listener1Model) { |
||||
|
dialog.show() |
||||
|
} |
||||
|
|
||||
|
override fun progress(task: DownloadTask, currentOffset: Long, totalLength: Long) { |
||||
|
dialog.progress = ((currentOffset / totalLength) * dialog.max).toInt() |
||||
|
} |
||||
|
|
||||
|
override fun taskEnd( |
||||
|
task: DownloadTask, |
||||
|
cause: EndCause, |
||||
|
realCause: Exception?, |
||||
|
model: Listener1Assist.Listener1Model |
||||
|
) { |
||||
|
dialog.dismiss() |
||||
|
Toast.makeText(this@MainActivity, "下载完成,开始安装!", Toast.LENGTH_SHORT).show(); |
||||
|
|
||||
|
doInstall(outputFile.absolutePath) |
||||
|
} |
||||
|
|
||||
|
override fun retry(task: DownloadTask, cause: ResumeFailedCause) { |
||||
|
} |
||||
|
|
||||
|
override fun connected( |
||||
|
task: DownloadTask, |
||||
|
blockCount: Int, |
||||
|
currentOffset: Long, |
||||
|
totalLength: Long |
||||
|
) { |
||||
|
} |
||||
|
|
||||
|
}) |
||||
} |
} |
||||
|
|
||||
private fun getXapkFilePath(): String { |
private fun doInstall(xapkFilePath: String) { |
||||
return "" |
val xapkInstaller = createXapkInstaller(xapkFilePath) |
||||
|
|
||||
|
if (xapkInstaller == null) { |
||||
|
Toast.makeText(this, "安装xapk失败!", Toast.LENGTH_SHORT).show(); |
||||
|
} else { |
||||
|
val installExecutor = Executors.newSingleThreadExecutor() |
||||
|
installExecutor.execute { |
||||
|
xapkInstaller.installXapk(this@MainActivity) |
||||
|
} |
||||
|
} |
||||
} |
} |
||||
|
|
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue