Adroid Studio app远程升级
手机APP开发完了,远程升级自动更新版本必不可少,不然每次更新版本就要重新安装,那就不合理了。刚开始感觉还没啥头绪,不会了就问百度,复制粘贴修修改改就搞定了,直接上代码:
首先要在AndroidManifest添加版本号。
远程升级类
package com.example.appview.Common; import android.app.DownloadManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.util.Log; import android.webkit.MimeTypeMap; import android.widget.Toast; import androidx.annotation.RequiresApi; import androidx.core.content.FileProvider; import java.io.File; import java.io.IOException; public class AppUpdataManger { private String tag = "AppUpdataManger"; private DownloadManager downloadManager; private Context mContext; private long mTaskId; private String downloadPath; private String versionName; public AppUpdataManger(Context context) { this.mContext = context; } //广播接收者,接收下载状态 private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { checkDownloadStatus();//检查下载状态 } }; @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void downloadAPK(String versionUrl, String versionName) { this.versionName = versionName; Log.e("下载", versionUrl + versionName); //将下载请求加入下载队列 downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE); //创建下载任务 DownloadManager.Request request = new DownloadManager.Request(Uri.parse(versionUrl)); request.setAllowedOverRoaming(false);//漫游网络是否可以下载 //设置文件类型,可以在下载结束后自动打开该文件 MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); String mimeString = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(versionUrl)); request.setMimeType(mimeString);//加入任务队列 //在通知栏显示,默认就是显示的 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); //设置通知栏标题 request.setTitle("Download"); request.setDescription("OYVFit Downloading..."); request.setAllowedOverRoaming(false); request.setVisibleInDownloadsUi(true); //设置下载的路径 File file = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), versionName); request.setDestinationUri(Uri.fromFile(file)); downloadPath = file.getAbsolutePath(); //加入下载列后会给该任务返回一个long型的id, //通过该id可以取消任务,重启任务等等 mTaskId = downloadManager.enqueue(request); //注册广播接收,监听下载状态 mContext.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); } //检查下载状态 private void checkDownloadStatus() { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(mTaskId);//赛选下载任务,传入任务ID,可变参数 Cursor cursor = downloadManager.query(query); if (cursor.moveToFirst()) { int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)); switch (status) { case DownloadManager.STATUS_PAUSED: //下载暂停 Log.d(tag, "下载暂停"); break; case DownloadManager.STATUS_PENDING: //下载延迟 Log.d(tag, "下载延迟"); break; case DownloadManager.STATUS_RUNNING: //正在下载 Log.d(tag, "正在下载"); break; case DownloadManager.STATUS_SUCCESSFUL: Toast.makeText(mContext, "下载完成", Toast.LENGTH_LONG).show(); //打开文件进行安装 installAPK(); break; case DownloadManager.STATUS_FAILED: //下载失败 Log.d(tag, "下载失败"); Toast.makeText(mContext, "更新失败", Toast.LENGTH_LONG).show(); break; } } cursor.close(); } //下载到本地后执行安装根据获得的id进行安装 protected void installAPK() { setPermission(downloadPath); Intent intent = new Intent(Intent.ACTION_VIEW); // 由于没有在Activity环境下启动Activity,设置下面的标签 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //Android 7.0以上要使用FileProvider if (Build.VERSION.SDK_INT >= 24) { File file = (new File(downloadPath)); //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致 参数3 共享的文件 Uri apkUri = FileProvider.getUriForFile(mContext, "com.example.appview.fileProvider", file); //添加这一句表示对目标应用临时授权该Uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.fromFile(new File(Environment.DIRECTORY_DOWNLOADS, versionName)), "application/vnd.android.package-archive"); } mContext.startActivity(intent); } //修改文件权限 private void setPermission(String absolutePath) { String command = "chmod " + "777" + " " + absolutePath; Runtime runtime = Runtime.getRuntime(); try { runtime.exec(command); } catch (IOException e) { e.printStackTrace(); } } }
判断远程是否需要升级是根据版本号来判断的,所以你要在数据库要有一个版本列表的。每次登录都要获取数据库中最新版本和本地版本作比较。较之低的话,启用远程升级。
package com.example.appview; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import android.Manifest; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; import com.example.appview.Common.AppUpdataManger; import com.example.appview.Common.HttpRequestHelper; import com.example.appview.Common.MyMD5; import com.example.appview.mian_page.Activity.LoginMainPage; import com.example.appview.mian_page.Frament.Preject_Tance_Frament.ItemA_Activity.Preject_Item_Img; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; public class MainActivity extends AppCompatActivity { private EditText user_edit; private EditText passward_edit; private CheckBox remeber_check; private Button login_btn; SharedPreferences sharedPreferences; SharedPreferences.Editor editor ;//获取编辑器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { finish(); return; } setContentView(R.layout.activity_main); user_edit=findViewById(R.id.user_edit); passward_edit=findViewById(R.id.passward_edit); remeber_check=findViewById(R.id.remeber_passward); login_btn=findViewById(R.id.login_btn); updateversion(); quanxian(); sharedPreferences = getSharedPreferences("userInfo", Context.MODE_PRIVATE); editor = sharedPreferences.edit();//获取编辑器 boolean isRemember = sharedPreferences.getBoolean("remember_password",false); if (isRemember){ String Name = sharedPreferences.getString("loginname",""); String Password = sharedPreferences.getString("userpassward",""); user_edit.setText(Name); passward_edit.setText(Password); remeber_check.setChecked(true); }else{ user_edit.setText(""); passward_edit.setText(""); remeber_check.setChecked(false); } login_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String username=user_edit.getText().toString(); String userpassward=passward_edit.getText().toString(); if (username.isEmpty()||userpassward.isEmpty()) { Toast.makeText(MainActivity.this, "用户名和密码不能为空!", Toast.LENGTH_LONG).show(); return; }else{ String repassward= MyMD5.MD5Capital(userpassward); String url="AppPro_UserLogin?username="+username+"&password="+repassward; new Thread(){ @Override public void run() { try { String result= HttpRequestHelper.get(url); Log.i("url",result); SaveUserInfo(result); } catch (JSONException | IOException e) { e.printStackTrace(); } } }.start(); } } }); } private void SaveUserInfo(String result) throws JSONException { JSONObject result_json=new JSONObject(result); Log.i("data=",result_json.toString()); if ( Integer.parseInt( result_json.getString("success"))==1){ int uid=0; JSONArray data=result_json.getJSONArray("data"); for (int i = 0; i < data.length(); i++) { JSONObject object=data.getJSONObject(i); uid=Integer.parseInt(object.getString("uid")); editor.putInt("UserID", Integer.parseInt(object.getString("uid"))); editor.putInt("DepartId", Integer.parseInt(object.getString("DepartId"))); editor.putString("departname",object.getString("departname")); editor.putString("realname",object.getString("realname")); editor.putString("Phone",object.getString("Phone")); } if (remeber_check.isChecked()){ //remember_password editor.putBoolean("remember_password",true); editor.putString("loginname",user_edit.getText().toString()); editor.putString("userpassward",passward_edit.getText().toString()); }else{ editor.putBoolean("remember_password",false); } //版本存储 editor.putString("banben",getVersionName(getApplicationContext())); editor.commit();//提交修改 Intent intent=new Intent(MainActivity.this, LoginMainPage.class); startActivity(intent); }else{ Message message=new Message(); message.what=1; handler.sendMessage(message); } } //数据回调 @SuppressLint("HandlerLeak") private Handler handler = new Handler() { @RequiresApi(api = Build.VERSION_CODES.N) @Override public void handleMessage(Message msg) { switch (msg.what){ case 1: Toast.makeText(MainActivity.this,"账号密码错误",Toast.LENGTH_SHORT).show(); break; case 2: try { SaveVersionInfo(msg.obj.toString()); } catch (JSONException e) { e.printStackTrace(); } break; default: break; } } }; private void updateversion(){ String updateurl="AppPro_UpLog"; new Thread(){ @Override public void run() { try { String result= HttpRequestHelper.get(updateurl); Message message=new Message(); message.what=2; message.obj=result; handler.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } }.start(); } @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) private void SaveVersionInfo(String result) throws JSONException { JSONObject result_json=new JSONObject(result); int versioncode=1; String versionname="1.0"; if ( Integer.parseInt( result_json.getString("success"))==1){ JSONArray data=result_json.getJSONArray("data"); for (int i = 0; i < data.length(); i++) { JSONObject object=data.getJSONObject(i); // Log.i("TW1",String.valueOf(object.getDouble("TW1"))+"°C"); versioncode=object.getInt("editionId"); versionname=object.getString("editionName"); } } int version= getVersionCode(getApplicationContext()); if (version<versioncode){ AppUpdataManger appUpdataManger=new AppUpdataManger(getApplicationContext()); appUpdataManger.downloadAPK("http://124.160.103.218:1111/upFile/app-release.apk",versionname); } } //版本名 public static String getVersionName(Context context) { return getPackageInfo(context).versionName; } //版本号 public static int getVersionCode(Context context) { return getPackageInfo(context).versionCode; } //获取版本info private static PackageInfo getPackageInfo(Context context) { PackageInfo pi = null; try { PackageManager pm = context.getPackageManager(); pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_CONFIGURATIONS); return pi; } catch (Exception e) { e.printStackTrace(); } return pi; } /** * 手机文件读写权限的授权 */ public void quanxian(){ if (Build.VERSION.SDK_INT >= 23) { int REQUEST_CODE_CONTACT = 101; String[] permissions = { Manifest.permission.WRITE_EXTERNAL_STORAGE}; //验证是否许可权限 for (String str : permissions) { if (MainActivity.this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) { //申请权限 MainActivity.this.requestPermissions(permissions, REQUEST_CODE_CONTACT); return; } else { //这里就是权限打开之后自己要操作的逻辑 } } } } }
.Net Core