隐藏

xamarin android 检测并下载更新功能

发布:2021/10/26 10:04:08作者:管理员 来源:本站 浏览次数:1071

//这里采用了asyncTask 异步任务
public class DownLoadTask : AsyncTask<System.String, Integer, System.Boolean>
    {
        private string url = "";
        private string mSavePath = "";
        private string fileName;
        private string versionName;
        private string ext;//文件后缀
        private int progress = 0;
        
        /// 需下载字节数
        private long MaxLength = 0;
      
        /// 当前已下载字节数
        private long CurrentLength = 0;
        private decimal Percent;
        public int updateTotalSize;
        private HttpMethod httpMethod;
 
       //下载完成后的处理事件
        public event Action<bool, string> Done;
 
        /// <summary>
        /// 进度更新的时候触发
        /// </summary>
        public event Action<int, decimal, long, long> OnUpdateProgress;
 
        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="versionName"></param>
        /// <param name="ext">文件后缀名</param>
        /// <param name="url">下载路径</param>
        public DownLoadTask(string fileName, string versionName, string ext, string url)
        {
            if (!IsCancelled)
            {
                this.httpMethod = HttpMethod.Get;
                this.fileName = fileName;
                this.versionName = versionName;
                this.ext = ext;
                this.url = url;
            }
        }
 
        public DownLoadTask(IntPtr a, JniHandleOwnership b) : base(a, b)
        {
        }
 
 
        protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
        {
            if (!IsCancelled)
            {
                return base.DoInBackground(@params);
            }
            else
            {
                return null;
            }
        }
        protected override bool RunInBackground(params string[] @params)
        {
            bool result = false;
 
            if (IsCancelled) { }
            else
            {
                try
                {
                    // 如果相等的话表示当前的sdcard挂载在手机上并且是可用的
                    if (Environment.ExternalStorageState.Equals(Environment.MediaMounted))
                    {
                       //下载apk服务器的地址
                        URL loadurl = new URL(url);
                       //保存apk地址        
                        var saveFolder = Environment.ExternalStorageDirectory + "/Download/";
                        if (!System.IO.Directory.Exists(saveFolder)) System.IO.Directory.CreateDirectory(saveFolder);
                        //先删除之前已下载过的apk
                        FileHelper.ReadAndDeleteApk(saveFolder, versionName, ext);
                        mSavePath = string.Format("{0}/{1}.V{2}{3}", saveFolder, fileName, versionName, ext);// fileName + "appName" + versionName + ext;
                        // 创建连接
                        HttpURLConnection conn = (HttpURLConnection)loadurl.OpenConnection();
                        conn.Connect();
                        updateTotalSize = conn.ContentLength;
                        this.MaxLength = updateTotalSize;
                        int totalSize = 0;
                        //输入流
                        var inputstream = conn.InputStream;
                        //缓存
                        int bufferLength = 1024;
                        byte[] buf = new byte[bufferLength];
                       
                        using (var fs = new FileStream(mSavePath, FileMode.Create))
                        {
                            int readsize = 0;
                            while (!IsCancelled && ((readsize = inputstream.Read(buf, 0, bufferLength)) != 0))
                            {
                                //写入文件
                                fs.Write(buf, 0, readsize);
 
                                totalSize += readsize;
                                this.CurrentLength = totalSize;
                                //计算进度条位置
                                var percend = (decimal)totalSize / (decimal)updateTotalSize;
                                this.Percent = percend;
                                progress = (int)(percend * 100);
                                Log.Debug("Download", "{0}/{1} {2:P4}", totalSize, updateTotalSize, percend);
 
                                PublishProgress(progress);
 
                            }
                        }
                        //写入到文件中
                        result = true;
                        inputstream.Close();
                        //TODO:校验文件完整性
                        //var fileLength = FileHelper.GetFileLength(mSavePath);
                        //if (fileLength != MaxLength)
                        //{
 
                        //}
                    }
                }
                catch (System.Exception ex)
                {
                    Log.Debug("load", ex.Message);
                }
            }
            return result;
        }
        protected override void OnPostExecute(System.Boolean aBoolean)
        {
            Done?.Invoke(aBoolean, mSavePath);
            Log.Debug("load", "下载的状态:" + aBoolean);
        }
        protected override void OnProgressUpdate(params Integer[] values)
        {
            base.OnProgressUpdate(values);
            if (values != null && values.Length > 0)
            {
                int val = (int)values[0];
                //  UpdateProgress?.Invoke(val);
                OnUpdateProgress?.Invoke(val, this.Percent, this.CurrentLength, this.MaxLength);
            }
        }

    }

//activity调用

public class SystemInfoActivity : Activity
{
    private  Context context;
    private bool isHasNew = false;
    private RelativeLayout checkNewBtn;//检查更新
    
    private CustomProgressDialog barDialog;
    private AlertDialog.Builder builder;
 
    protected override void OnCreate(Bundle savedInstanceState)
    {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layo ut.SystemInfo);
             //。。。。。获取页面布局元素
            context = this;
            checkNewBtn = FindViewById<RelativeLayout>(Resource.Id.checkNewBtn);
            checkNewBtn.Click -= CheckNewBtn_Click;
            checkNewBtn.Click += CheckNewBtn_Click;
           //先查询服务器上面最新的app版本
            CheckNew();
 
    }
   //请求api,检测最新版本的信息
 
    private void CheckNew()
    {
      //请求接口的代码省略。。。。
      //返回的结果
        if (result.Content.AppVersion > AppInfo.VersionCode)
         {
            isHasNew = true;   
         }
    }
    private void CheckNewBtn_Click(object sender, EventArgs e)
    {
      if (isHasNew)
      {
          OpenUpDialog();
      }
      else
      {
          MyDialog.showMessage(context, "当前已是最新版本无需更新");
      }
    }
   //
    private void OpenUpDialog()
    {
      builder = new AlertDialog.Builder(mContext);
      builder.SetTitle("有新版本啦").SetMessage("我更新再更新").SetNeutralButton("暂不更新",
      (s,e)=> { }).setPositiveButton("立即更新",(s,e)=>{
        //先检测一遍是否有访问权限
         if (CheckFilePermission())
         {
           DownloadApk(content.AppVersionCode, content.DownloadURL);
         }
         else
         {
 
           MyDialog.showMessage(context, "需要获得访问存储卡的权限,您可以在设置->应用->权限
           进行设置!");
          }
 
      }).Show();
             
     }
    //查看是否打开了使用存储的读写权限
    private bool CheckFilePermission()
    {
      var result = false;
      // 需要在Android里面找到你要开的权限
      string readPermission = Manifest.Permission.ReadExternalStorage;
      string writerPermission = Manifest.Permission.WriteExternalStorage;
      if (PermissionChecker.CheckSelfPermission(context, readPermission) ==
          PermissionChecker.PermissionGranted &&
          PermissionChecker.CheckSelfPermission(context, writerPermission) ==
          PermissionChecker.PermissionGranted)
          {
                result = true;
          }
            return result;
     }
    //下载
    private void DownloadApk(string versionName, string url)
    {
      //自定义的进度条弹窗
       barDialog = new CustomProgressDialog(context);
       barDialog.show(0, "0 / 0");
       DownLoadTask loadtask = new DownLoadTask("appName", versionName, ".apk", url);
       loadtask.Execute();
       loadtask.OnUpdateProgress += Loadtask_OnUpdateProgress;
       loadtask.Done += Loadtask_Done;
    }
   //更新进度条的值
    private void Loadtask_OnUpdateProgress(int progress, decimal percent, long currentLength, long maxLength)
    {
       var stringCurrentLen = StringHelper.ToByteString(currentLength);
       var stringmaxLen = StringHelper.ToByteString(maxLength);
       barDialog.update(progress, stringCurrentLen + " / " + stringmaxLen);
    }
    //下载完成的时候
    private void Loadtask_Done(bool isLoaded, string savePath)
    {
       barDialog.dismiss();
       if (isLoaded)
       {
         InstallApk(savePath);
       }
       else
       {
         MyDialog.showToast(context, "下载失败", 1);
       }
    }
   //开始安装
    private void InstallApk(string savePath)
    {
      if (System.IO.File.Exists(savePath))
      {
         try
         {
            Intent i = new Intent(Intent.ActionView);
            i.SetDataAndType(Uri.FromFile(new File(savePath)), "application/vnd.android.package-archive");
            i.SetFlags(ActivityFlags.NewTask);
            tartActivity(i);
         }
         catch (Exception)
         {
            MyDialog.showToast(context, "安装失败", 1);
         }
      }
      else
      {
        MyDialog.showToast(context, "未找到安装包的文件路径", 1);
      }
    }
 }

//自定义进度条弹窗布局

<?xml version="1.0" encoding="utf-8"?>
<!--更新新版版本下载时的进度条-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@color/white"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:paddingLeft="15dp"
        android:text="正在下载" />
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="20dp"
        android:minHeight="20dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:progress="0" />
     <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:paddingLeft="15dp"
        android:text="zz" />
</LinearLayout>