1.检查更新的页面
2.接受广播的页面(BaseActivity)每个activity都继承它,这样随时都可以弹出更新弹框
3.前台服务
注意:activity 和service用android studio自动生成否则自己往
AndroidManifest里面加内容。
package com.rengda.updateapplication
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AlertDialog
import androidx.core.app.NotificationCompat
class MainActivity : BaseActivity() {
val myPackageName="com.rengda.updateapplication" //包名
val TAG="MainActivity"
lateinit var context: Context
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
context=this
getVersion()
}
//去服务器查询最新版本
private fun getVersion(){
var latestVersion=12;//虚假的得到 其实要去服务
checkUpdate(latestVersion)
}
private fun checkUpdate(latestVersion:Int){
val version:Int= if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageManager.getPackageInfo(myPackageName, 0).longVersionCode.toInt()
} else {
packageManager.getPackageInfo(myPackageName, 0).versionCode
}
// Log.d(TAG, "当前版本号:${version},最新版本号:${latestVersion}")
//小于接口版本号 发送广播
if (version
package com.rengda.updateapplication
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
open class BaseActivity : AppCompatActivity() {
val updateAction="com.renda.com" //广播的动作,根据这个来接受广播
lateinit var receiver:UpdateReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_base)
//广播接收器 注册
val intentFilter= IntentFilter()
intentFilter.addAction(updateAction)
receiver=UpdateReceiver()
registerReceiver(receiver,intentFilter)
}
//广播接收器
inner class UpdateReceiver: BroadcastReceiver(){
override fun onReceive(context: Context?, intent: Intent?) {
showUpdateDialog()
}
}
//显示更新下载框 点击确定进行下载 开启通知
private fun showUpdateDialog(){
AlertDialog.Builder(this).apply {
setTitle("更新")
setMessage("当前版本低于最新版本,请前往更新!")
setCancelable(false)
setPositiveButton("确定"){
dialog, which ->
val intent=Intent(context,DownloadService::class.java)
startService(intent)
}
show()
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
}
}
如果要自动安装涉及到fileprovider 这里就没详写
package com.rengda.updateapplication
import android.R.attr.path
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Binder
import android.os.Build
import android.os.Environment
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.content.FileProvider
import java.io.File
import java.io.FileOutputStream
import java.net.HttpURLConnection
import java.net.URL
import javax.net.ssl.HttpsURLConnection
import kotlin.concurrent.thread
class DownloadService : Service() {
private lateinit var context:Context
private var downloadFile:String=""
override fun onBind(intent: Intent): IBinder {
TODO("Return the communication channel to the service.")
}
override fun onCreate() {
super.onCreate()
context=this
setForground()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
thread {
doDownLoad("下载地址")//去下载
}
return super.onStartCommand(intent, flags, startId)
}
private fun doDownLoad(url:String){
var connection: HttpsURLConnection? = null
val url = URL(url)
connection = url.openConnection() as HttpsURLConnection
connection.connectTimeout = 10000
connection.readTimeout = 10000
connection.requestMethod = "GET"
val input = connection.inputStream
val intcount=connection.getContentLength()//获取总长度
var byteArray=ByteArray(1024)
val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
val file= File(storageDir?.absolutePath+"/仓储一体化.apk")
if (file.exists()){
file.delete()
}else{
file.createNewFile()
}
downloadFile=storageDir?.absolutePath+"/仓储一体化.apk"
val fos = FileOutputStream(file)
var downLoadSize=0;
while (true){
var numread=input.read(byteArray)
if (numread==-1){
break
}else{
fos.write(byteArray,0,numread)
downLoadSize=downLoadSize+numread
var process=((downLoadSize.toDouble()/intcount)*100).toInt()
sendNotification("下载进度:${process}%")
}
}
if (intcount==downLoadSize){
sendSuccessNotification("下载成功!")
doInstall()
}else{
sendNotification("下载失败!")
if (file.exists()){
file.delete()
}
stopSelf()
}
}
//开启前台服务
private fun setForground(){
val manager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
val channel=NotificationChannel("my_service","前台Service通知",NotificationManager.IMPORTANCE_DEFAULT)
manager.createNotificationChannel(channel)
}
val notification=NotificationCompat.Builder(this,"my_service")
.setContentTitle("开启下载")
.setSmallIcon(R.mipmap.ic_launcher)
.build()
startForeground(1,notification)
}
private fun sendNotification(msg:String){
val manager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
val channel=NotificationChannel("my_service","前台Service通知",NotificationManager.IMPORTANCE_DEFAULT)
manager.createNotificationChannel(channel)
}
val notification=NotificationCompat.Builder(this,"my_service")
.setContentTitle("下载")
.setContentText(msg)
.setSmallIcon(R.mipmap.ic_launcher)
.build()
startForeground(2,notification)
}
//前台服务 这个可以进行点击跳转到安装页面
private fun sendSuccessNotification(msg:String){
val manager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
val channel=NotificationChannel("my_service","前台Service通知",NotificationManager.IMPORTANCE_DEFAULT)
manager.createNotificationChannel(channel)
}
val pi= PendingIntent.getActivity(context,0,getInstallIntent(),0)
val notification=NotificationCompat.Builder(this,"my_service")
.setContentTitle("下载")
.setContentText(msg)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pi)
.build()
startForeground(3,notification)
}
private fun getInstallIntent():Intent{
val intent = Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//这里的authority是自己在AndroidManifest.xml定义的
var apkUri = FileProvider.getUriForFile(context,"com.rengda.fileprovider",File(downloadFile))
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(File(downloadFile)), "application/vnd.android.package-archive");
}
return intent
}
private fun doInstall(){
context.startActivity(getInstallIntent());
}
}
file_paths.xml
权限的声明,activity和service和fileprovider的声明。