精华内容
下载资源
问答
  • } /** * 不更新版本 */ public void notNewVersionUpdate(){ int verCode = this.getVerCode(this); String verName = this.getVerName(this); StringBuffer sb = new StringBuffer(); sb.append("当前版本:"); sb...

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    package com.update.apk;

    import java.io.BufferedReader;

    import java.io.File;

    import java.io.FileOutputStream;

    import java.io.InputStream;

    import java.io.InputStreamReader;

    import java.net.HttpURLConnection;

    import java.net.URL;

    import org.apache.http.HttpEntity;

    import org.apache.http.HttpResponse;

    import org.apache.http.client.HttpClient;

    import org.apache.http.client.methods.HttpGet;

    import org.apache.http.impl.client.DefaultHttpClient;

    import org.json.JSONArray;

    import org.json.JSONObject;

    import android.app.Activity;

    import android.app.AlertDialog;

    import android.app.Dialog;

    import android.app.ProgressDialog;

    import android.content.Context;

    import android.content.DialogInterface;

    import android.content.Intent;

    import android.content.pm.PackageManager.NameNotFoundException;

    import android.net.Uri;

    import android.os.Bundle;

    import android.os.Environment;

    import android.os.Handler;

    import android.os.Message;

    import android.util.Log;

    public class MainActivity extends Activity {

    /** Called when the activity is first created. */

    String newVerName = "";//新版本名称

    int newVerCode = -1;//新版本号

    ProgressDialog pd = null;

    String UPDATE_SERVERAPK = "ApkUpdateAndroid.apk";

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    if(getServerVer()){

    int verCode = this.getVerCode(this);

    if(newVerCode>verCode){

    doNewVersionUpdate();//更新版本

    }else{

    notNewVersionUpdate();//提示已是最新版本

    }

    }

    }

    /**

    * 获得版本号

    */

    public int getVerCode(Context context){

    int verCode = -1;

    try {

    verCode = context.getPackageManager().getPackageInfo("com.update.apk", 0).versionCode;

    } catch (NameNotFoundException e) {

    // TODO Auto-generated catch block

    Log.e("版本号获取异常", e.getMessage());

    }

    return verCode;

    }

    /**

    * 获得版本名称

    */

    public String getVerName(Context context){

    String verName = "";

    try {

    verName = context.getPackageManager().getPackageInfo("com.update.apk", 0).versionName;

    } catch (NameNotFoundException e) {

    Log.e("版本名称获取异常", e.getMessage());

    }

    return verName;

    }

    /**

    * 从服务器端获得版本号与版本名称

    * @return

    */

    public boolean getServerVer(){

    try {

    URL url = new URL("http://10.0.2.2:8080/ApkUpdateService/ver");

    HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();

    httpConnection.setDoInput(true);

    httpConnection.setDoOutput(true);

    httpConnection.setRequestMethod("GET");

    httpConnection.connect();

    InputStreamReader reader = new InputStreamReader(httpConnection.getInputStream());

    BufferedReader bReader = new BufferedReader(reader);

    String json = bReader.readLine();

    JSONArray array = new JSONArray(json);

    JSONObject jsonObj = array.getJSONObject(0);

    newVerCode = Integer.parseInt(jsonObj.getString("verCode"));

    newVerName = jsonObj.getString("verName");

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    return false;

    }

    return true;

    }

    /**

    * 不更新版本

    */

    public void notNewVersionUpdate(){

    int verCode = this.getVerCode(this);

    String verName = this.getVerName(this);

    StringBuffer sb = new StringBuffer();

    sb.append("当前版本:");

    sb.append(verName);

    sb.append(" Code:");

    sb.append(verCode);

    sb.append("

    已是最新版本,无需更新");

    Dialog dialog = new AlertDialog.Builder(this)

    .setTitle("软件更新")

    .setMessage(sb.toString())

    .setPositiveButton("确定", new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog, int which) {

    // TODO Auto-generated method stub

    finish();

    }

    }).create();

    dialog.show();

    }

    /**

    * 更新版本

    */

    public void doNewVersionUpdate(){

    int verCode = this.getVerCode(this);

    String verName = this.getVerName(this);

    StringBuffer sb = new StringBuffer();

    sb.append("当前版本:");

    sb.append(verName);

    sb.append(" Code:");

    sb.append(verCode);

    sb.append(",发现版本:");

    sb.append(newVerName);

    sb.append(" Code:");

    sb.append(verCode);

    sb.append(",是否更新");

    Dialog dialog = new AlertDialog.Builder(this)

    .setTitle("软件更新")

    .setMessage(sb.toString())

    .setPositiveButton("更新", new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog, int which) {

    // TODO Auto-generated method stub

    pd = new ProgressDialog(MainActivity.this);

    pd.setTitle("正在下载");

    pd.setMessage("请稍后。。。");

    pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);

    downFile("http://10.0.2.2:8080/ApkUpdateService/ApkUpdateAndroid.apk");

    }

    })

    .setNegativeButton("暂不更新", new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog, int which) {

    // TODO Auto-generated method stub

    finish();

    }

    }).create();

    //显示更新框

    dialog.show();

    }

    /**

    * 下载apk

    */

    public void downFile(final String url){

    pd.show();

    new Thread(){

    public void run(){

    HttpClient client = new DefaultHttpClient();

    HttpGet get = new HttpGet(url);

    HttpResponse response;

    try {

    response = client.execute(get);

    HttpEntity entity = response.getEntity();

    long length = entity.getContentLength();

    InputStream is = entity.getContent();

    FileOutputStream fileOutputStream = null;

    if(is != null){

    File file = new File(Environment.getExternalStorageDirectory(),UPDATE_SERVERAPK);

    fileOutputStream = new FileOutputStream(file);

    byte[] b = new byte[1024];

    int charb = -1;

    int count = 0;

    while((charb = is.read(b))!=-1){

    fileOutputStream.write(b, 0, charb);

    count += charb;

    }

    }

    fileOutputStream.flush();

    if(fileOutputStream!=null){

    fileOutputStream.close();

    }

    down();

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }.start();

    }

    Handler handler = new Handler() {

    @Override

    public void handleMessage(Message msg) {

    super.handleMessage(msg);

    pd.cancel();

    update();

    }

    };

    /**

    * 下载完成,通过handler将下载对话框取消

    */

    public void down(){

    new Thread(){

    public void run(){

    Message message = handler.obtainMessage();

    handler.sendMessage(message);

    }

    }.start();

    }

    /**

    * 安装应用

    */

    public void update(){

    Intent intent = new Intent(Intent.ACTION_VIEW);

    intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory(),UPDATE_SERVERAPK))

    , "application/vnd.android.package-archive");

    startActivity(intent);

    }

    }

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    展开全文
  • Android如何更新app的版本(中级)版本更新看看我们要用到哪些技术1自定义通知栏2 HTTP下载3 AsyncTask4刷新通知栏中的进度条5执行 apk安装的隐士意图6 Toast7签名(安装时系统会自动检测签名是否一致)8获得服务端和...

    Android如何更新app的版本(中级)

    版本更新

    看看我们要用到哪些技术1自定义通知栏

    2 HTTP下载

    3 AsyncTask

    4刷新通知栏中的进度条

    5执行 apk安装的隐士意图

    6 Toast

    7签名(安装时系统会自动检测签名是否一致)

    8获得服务端和客户端的版本号

    上代码

    (1)点击事件判断是否有新版本更新 (2)自定义一个通知 同时刷新下载进度

    (3)异步下载新版本app(4)隐士意图来安装

    首先别忘了写权限!!!!!超爱忘得东西 恨死它了

    private Runnable mrun;

    private NotificationManager mNotificationManager;

    private Notification notification;

    private RemoteViews remoteviews;

    private int count;

    private int loadversion;

    private int version;

    //升级按钮点击事件的方法 通过服务器来解析JSON 得到版本号 判断是否来通知下载

    private void upgrade() {

    PackageManager nPackageManager=getPackageManager();//得到包管理器

    try {

    PackageInfo nPackageInfo=nPackageManager

    .getPackageInfo(getPackageName(),PackageManager.GET_CONFIGURATIONS );

    loadversion=nPackageInfo.versionCode;//得到现在app的版本号

    }catch (NameNotFoundException e1) {

    // TODO Auto-generated catch block

    e1.printStackTrace();

    }

    //服务器端通过GET 得到JSON

    String json=JSandBitmap.httpGetDemo("http://192.168.14.234/version.json");

    try {

    JSONArray jsonArray=new JSONArray(json);

    JSONObject jsonObject=jsonArray.getJSONObject(0);

    version = jsonObject.getInt("version");//得到服务端的app版本号

    }catch (JSONException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    if((loadversion

    sendNotification();

    }else{//如果没有 弹出对话框告知用户

    new AlertDialog.Builder(this)

    .setTitle("update cancel")

    .setMessage("Sorry Not new Version ")

    .setNegativeButton("cencel", null).show();

    }

    }

    //此方法来发送下载通知 采用的是自定义通知栏 并且更加下载的进度来刷新进度条

    //自定义通知的方法 在上上篇的博文中 这里不做太多的解释

    private void sendNotification() {

    mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    notification = new Notification(

    R.drawable.player_play_light, "Midiplay",

    System.currentTimeMillis());

    remoteviews= new RemoteViews("com.tarena.gsd110623.midiplayonline", R.layout.mynotiifcation);

    remoteviews.setImageViewResource(R.id.p_w_picpathView1, R.drawable.a00);

    notification.contentView=remoteviews;

    Intent intent=new Intent(this,install.class);//PendingIntent 调用的系统的安装隐士意图 后面红色的代码

    PendingIntent pendingintent=PendingIntent.getActivity(this, 0, intent, 0);

    notification.contentIntent=pendingintent;

    mrun=new Runnable() {//这个Runnable 用来根据下载进度来刷新进度条

    @Override

    public void run() {

    if(count<98){//紫色的count 是异步下载计算出来设置进度的值

    remoteviews.setProgressBar(R.id.progressBar1, 100, count, false);

    remoteviews.setTextViewText(R.id.textView1, count+"%");

    mNotificationManager.notify(8888, notification);

    handler.postDelayed(mrun, 300);

    }else{//这里计算出来的count 不是那么准确 所以下载完成后 给一个固定值做为下载完成

    remoteviews.setProgressBar(R.id.progressBar1, 100, 100, false);

    remoteviews.setTextViewText(R.id.textView1, 100+"%");

    mNotificationManager.notify(8888, notification);

    Toast.makeText(Welcome.this, "download over", Toast.LENGTH_SHORT);//提示用户下载成功

    }

    }

    };

    handler.postDelayed(mrun, 300);

    Update_AsyncTask mUpdate_AsyncTask=new Update_AsyncTask();

    try {//启动下载

    mUpdate_AsyncTask.execute(new URL("http://192.168.14.234/android_project_midiplayonline.apk"));

    }catch (MalformedURLException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    //这个内部类用来异步下载新版本app 通过服务端下载这里不多说了

    class Update_AsyncTask extends AsyncTask{

    @Override

    protected Object doInBackground(URL... params) {

    // TODO Auto-generated method stub

    try {

    URLConnection con = params[0].openConnection();

    if (HttpURLConnection.HTTP_OK != ((HttpURLConnection)con).getResponseCode())

    {

    Log.i("Main", "connection failed");

    return null;

    }

    InputStream is = con.getInputStream();

    int contentlength=con.getContentLength();//得到下载的总长度

    System.out.println(contentlength);

    File file=new File(Constant.APK_FILE_PATH);

    if(!file.exists()){

    file.getParentFile().mkdirs();

    file.createNewFile();

    }

    FileOutputStream out=new FileOutputStream(file);

    int current = 0;

    int x=0;

    byte[]arr=new byte[1024];

    while ( (current = is.read(arr)) != -1 ){

    out.write(arr, 0, current);

    x=x+current;

    count=(int)(100*x/contentlength);//计算下载的百分百

    }

    is.close();

    }catch (Exception e) {

    }return null;

    }

    }

    /*

    * 此类为系统安装的隐士意图

    */

    public class install extends Activity{

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    // TODO Auto-generated method stub

    super.onCreate(savedInstanceState);

    Intent notify_Intent = new Intent(Intent.ACTION_VIEW);

    notify_Intent.setDataAndType(Uri.fromFile(new File(Constant.APK_FILE_PATH)), "application/vnd.android.package-archive");

    startActivity(notify_Intent);

    //取消上一个通知

    NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    nm.cancel(8888);

    overridePendingTransition(0, 0);

    finish();

    }

    }

    效果如下

    257ba9e703db4b2e73d383e7dd6871aa.png

    展开全文
  • 快速自动更新Android Studio版本  在开发过程中,有些时候总是会报一些Android Studio vesion 版本低,要求升级之类的错误,然而大家又会嫌麻烦去网上下载,今天给大家介绍的一个小技巧是,在Android Studio...

    快速自动更新Android Studio版本

           在开发过程中,有些时候总是会报一些Android Studio vesion  版本低,要求升级之类的错误,然而大家又会嫌麻烦去网上下载,今天给大家介绍的一个小技巧是,在Android Studio里面直接就能升级的小方法,我们来看看怎样升级;


            第一步: 打开Settings, 找到 下图 1所指的Systym Settings 下面的Updates,然后就会出现右边的界面,都选 2 所指的自动查找版本更新,我的版本是2.0preview2,太老了 ,我都是喜欢体验最新版的,现在我就是点击的Beta 渠道下载,还不是正式版。然后点击 3所指的检查,如果有最新版就会弹出 4 所指的更新提示beta 6 版本,(要想从官方google获取到更新,你的网络要翻墙,这点大家要记住自己的网是不是已经翻墙了,如果没有翻墙我不敢保证你能收到更新,要翻墙大家百度下,都应该知道用vpn吧,你们不懂翻墙就百度下。 )更新内容是从我的2.0 preview2 到beta6之间的累计更新,总共有53Mb,点击 5所指的更新和重启;


          点击更新后,就出现了如下的更新进度条。然后等待更新完毕。


              重启后就看到自己的Android Studio 版本为 2.0 Beta 6 了。


                这里在讲讲 Android Studio各个版本之间的差别;如下图


           可以看到版本有4种渠道更新,他们的特点如下:

             CanaryChannel :金丝雀版,  能获取最新的功能(Bug较多 并且都还没有验证)

           Develop Channel: 开发者版,到了这个版本大Bug都得到了解决;

           Beta Channel:测试版,到这里很多小bug都得到了解决,问题还有点,基本可能是我们遇不到的;

           Stable Channel:正式稳定版,到这里就是官方推荐的最新正式版,不过要等很久,各项功能都很稳定,基本没问题了。适合刚接触AndroidStudio的人使用,和那些最求稳定的开发人员。想我这样喜欢尝鲜的开发人员,就喜欢使用最新的beta版本。哈哈。

            好了这里给大家介绍了Android Studio 翻墙更新版本的小技巧。  希望对大家的工作和学习有帮助,祝大家学习快乐!天天进步一点!

    展开全文
  • 更新应用的最新版本是每个上线apk都必须有的功能。 那么这个功能要怎样实现呢? 一、首先我们理一下具体的思路:  1、最好采用异步请求的方式与服务器交互。即创建一个类,继承AsyncTask类。  2、判断当前的...

    更新应用的最新版本是每个上线apk都必须有的功能。

    那么这个功能要怎样实现呢?

    一、首先我们理一下具体的思路:

      1、最好采用异步请求的方式与服务器交互。即创建一个类,继承AsyncTask类。

      2、判断当前的(即客户端)apk版本是否小于服务器端的apk版本,如果小于,则向服务器端发送请求下载最新版本的apk。

      3、下载最新的apk后,必须在客户端创建一个路径用来存放下载好的apk文件。所以在这一步之前,需在客户端创建一个路径。

      4、下载apk得花费一点时间,为了更好的用户体验,我们最好写一个进度框或一个动画显示正在下载的进度或者提示用户apk正在更新。

      5、通过更新apk接口,取得服务器返回的json或xml数据,包括最新的版本信息、下载apk的url、MD5、文件大小。解析json或xml数据,并将数据保存到一个bean文件中。

      6、通过HttpClient取得服务器返回的安装包数据,保存到输入流中。

      7、将安装包数据保存为一个.tmp文件。如:安装包名为news,则保存的文件名为news.tmp。

      8、当安装包数据全部读取完成后,再将.tmp文件改名为以安装包名相同的文件,即news。

      9、将文件news进行解压,即可得到.apk文件。

     

    二、具体实现代码:

    SettingActivity.java :
      1 public class SettingActivity extends Activity {
      2     private UpdateApkTask updateApkTask;// 更新apk线程
      3     private ProgressDialog progressDialog;// 删除文件及数据库的load界面
      4     
      5    @Override
      6     protected void onCreate(Bundle savedInstanceState) {
      7         super.onCreate(savedInstanceState);
      8 
      9         setContentView(R.layout.activity_setting);
     10 
     11         initUI();
     12         restorationDialog();
     13         
     14     }
     15 
     16     protected void initUI() {
     17         updateApk();
     18     }
     19 
     20 /**
     21      * 初始化progressDialog
     22      */
     23     private void restorationDialog() {
     24 
     25         progressDialog = new ProgressDialog(this);
     26         progressDialog.setMessage(getString(R.string.restore_pDialog_title));
     27         progressDialog.setTitle(getString(R.string.hint));
     28         progressDialog.setCancelable(false);// 不可撤销
     29 
     30     }
     31 
     32     private updateApk(){
     33       stopUpdateApkTask();
     34        updateApkTask = new UpdateApkTask();
     35        FileUtils2.createFile(MyMount
     36            .getImageStorageDir(SettingActivity.this));
     37 
     38        updateApkTask.execute(new String[] { MyMount
     39            .getImageStorageDir(SettingActivity.this) });
     40     }
     41 
     42 /**
     43      * 更新程序版本线程
     44      *
     45      */
     46     private class UpdateApkTask extends AsyncTask<String, Integer, Boolean> {
     47 
     48         private boolean tag = false;
     49         public UpdateApkTask() {
     50             progressDialog.show();
     51             progressDialog.setMessage(getString(R.string.apk_pDialog_title));
     52         }
     53 
     54         // onPreExecute方法用于在执行后台任务前做一些UI操作
     55         @Override
     56         protected void onPreExecute() {
     57 
     58             super.onPreExecute();
     59 
     60         }
     61 
     62         // doInBackground方法内部执行后台任务,不可在此方法内修改UI
     63         @Override
     64         protected Boolean doInBackground(String... params) {
     65             CodeUpdate mCodeUpdate = NetworkDataUpdate.getInstance(
     66                     SettingActivity.this).GetCodeUpdate();
     67             if (mCodeUpdate != null && mCodeUpdate.getUpdatePackName() != null) {
     68 
     69                 // 如果用户当前的apk版本号小于服务器中的apk版本号,则下载最新版本的apk
     70                 if (Float.parseFloat(VersionUtil.getVersionCode(SettingActivity.this)) < Float
     71                         .parseFloat(mCodeUpdate.getVersion())) {
     72                     tag = true;
     73                     String downloadPath = mCodeUpdate.getUpdatePackName();// 获取URL
                  //如果url加了密,比如是这种形式:"http://<Dns>:<Port>/api/json/reply/",则要进行解密操作
    74 downloadPath = downloadPath.replace("<Dns>",KeltiIntenface.ipStr).replace("<Port>",KeltiIntenface.postStr);// 替换URL的ip及post 75 76 InputStream is = null; 77 FileOutputStream fos = null; 78 File tmpFile = null; 79 80 try { 81 HttpClient httpClient = new DefaultHttpClient(); 82 HttpGet httpGet = new HttpGet(downloadPath); 83 HttpResponse httpResponse = httpClient.execute(httpGet); 84 HttpEntity entity = httpResponse.getEntity(); 85 is = entity.getContent(); 86 87 if (httpResponse.getStatusLine().getStatusCode() != 200) { 88 89 return false; 90 } 91 // 新建文件,下载文件 92 tmpFile = new File(params[0] 93 + downloadPath.substring(downloadPath 94 .lastIndexOf("/") + 1) + ".tmp"); 95 96 if (is != null) { 97 fos = new FileOutputStream(tmpFile); 98 byte[] buf = new byte[1024 * 1024 * 4]; 99 int ch = -1; 100 while ((ch = is.read(buf)) != -1) { 101 fos.write(buf, 0, ch); 102 } 103 } 104 105 fos.flush(); 106 if (fos != null) { 107 fos.close(); 108 } 109 if (is != null) { 110 tmpFile.renameTo(new File(params[0] 111 + downloadPath.substring(downloadPath 112 .lastIndexOf("/") + 1))); 113 114 File mFile = new File(params[0] 115 + downloadPath.substring(downloadPath 116 .lastIndexOf("/") + 1)); 117                 //解压下载完成后的文件,将mFile文件解压到params[0]目录,且解压完成后,将压缩包删除,以节省客户端的存储空间 118 if (DecompressionZip.upZipFile(mFile, params[0]) == 0) { 119 120 YLogUtil.printSpidLog("mFile="+mFile.toString()); 121 mFile.delete(); 122 return true; 123 } 124 125 } 126 } catch (ConnectException connectException) { 127 128 if (tmpFile != null && tmpFile.exists()) { 129 YLogUtil.printSpidLog("tmpFile="+tmpFile.toString()); 130 tmpFile.delete(); 131 } 132 connectException.printStackTrace(); 133 134 } catch (SocketTimeoutException socketTimeoutException) { 135 136 if (tmpFile != null && tmpFile.exists()) { 137 YLogUtil.printSpidLog("tmpFile="+tmpFile.toString()); 138 tmpFile.delete(); 139 } 140 socketTimeoutException.printStackTrace(); 141 142 } catch (Exception e) { 143 e.printStackTrace(); 144 145 } 146 } 147 148 } 149 return false; 150 } 151 152 // onProgressUpdate方法用于更新进度信息 153 @Override 154 protected void onProgressUpdate(Integer... values) { 155 156 super.onProgressUpdate(values); 157 } 158 159 // onPostExecute方法用于在执行完后台任务后更新UI,显示结果 160 @Override 161 protected void onPostExecute(Boolean result) { 162 163 super.onPostExecute(result); 164 165 progressDialog.dismiss(); 166 if (result) { 167 168 ToastUtils.showToast(SettingActivity.this, 169 getString(R.string.toast_download_succeed), false); 170 FileUtils2.openFile( 171 SettingActivity.this, 172 new File(MyMount 173 .getImageStorageDir(SettingActivity.this) 174 + YContants.apkPath)); 175 } else { 176 // 如果用户当前的apk版本号等于服务器中的apk版本号,则告诉用户已经是最新版本 177 if (!tag) { 178 ToastUtils.showToast(SettingActivity.this, getString(R.string.latestVersion), true); 179 180 }else { 181 ToastUtils.showToast(SettingActivity.this, 182 getString(R.string.toast_download_fail), false); 183 } 184 } 185 186 } 187 188 // onCancelled方法用于在取消执行中的任务时更改UI 189 @Override 190 protected void onCancelled() { 191 192 super.onCancelled(); 193 progressDialog.dismiss(); 194 } 195 196 } 197 198 private void stopUpdateApkTask() { 199 if (updateApkTask != null && !updateApkTask.isCancelled()) { 200 updateApkTask.cancel(true); 201 } 202 } 203 204 @Override 205 protected void onDestroy() { 206 207 stopUpdateApkTask(); 208 super.onDestroy(); 209 } 210 211 }

     

    FileUtils2.java:

    public class FileUtils2 {
    
        /**
         * 创建文件夹
         * 
         * @param pathString
         *            文件夹路径
         */
        public static boolean createFile(String pathString) {
            if (pathString == null || pathString.equals("")
                    || pathString.equals("null") || !pathString.contains("/")) {
    
                return false;
            } else {
                File file = new File(pathString.substring(0,
                        pathString.lastIndexOf("/") + 1));
    
                if (!file.exists()) {
    
                    try {
    
                        // 按照指定的路径创建文件夹
    
                        file.mkdirs();
    
                    } catch (Exception e) {
    
                        e.printStackTrace();
    
                        return false;
                    }
    
                }
                return fileCanReadWrite(file);
    
            }
        }
    
        /**
         * 判断文件夹/文件是否可读写
         * 
         * @param file
         *            文件路径
         * @return
         */
        public static boolean fileCanReadWrite(File file) {
            if (file.canWrite() && file.canRead()) {
                return true;
            } else {
                return false;
            }
        }

    /**
         * 安装程序
         * 
         * @param context    上下文
         * @param file    apk的保存路径
         */
        public static void openFile(Context context, File file) {
            try {
                Intent mIntent = new Intent();
                mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                mIntent.setAction(android.content.Intent.ACTION_VIEW);
                mIntent.setDataAndType(Uri.fromFile(file),
                        "application/vnd.android.package-archive");
    
                context.startActivity(mIntent);
    
            } catch (Exception e) {
                e.printStackTrace();
    
                ToastUtils.showToast(
                        context,
                        context.getResources().getString(
                                R.string.toast_openApk_error), false);
            }
    
        }
    
    

     

    
    }

     

    ToastUtils.java:

    public class ToastUtils {
    
        
        public static void showToast(Context context, String msg, Boolean isTimeLong){  
            int time = Toast.LENGTH_SHORT;  
            if(isTimeLong){  
                time = Toast.LENGTH_LONG;  
            }  
              
            Toast toast = Toast.makeText(context, null, time);  
            LinearLayout layout = (LinearLayout)toast.getView();   
           
            layout.setBackgroundResource(R.drawable.toast_bg);
            layout.setOrientation(LinearLayout.VISIBLE);  
            layout.setGravity(Gravity.CENTER);  
            TextView tv = new TextView(context);  
            tv.setLayoutParams(new  LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));     
            tv.setGravity(Gravity.CENTER);  
            tv.setTextColor(Color.parseColor("#000000"));  
            tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30);  
            tv.setPadding(0, 0, 0, 0);  
            tv.setText(msg);  
            layout.addView(tv);  
            toast.show();  
        }  
    }

     

    MyMount.java:

    public class MyMount {
    /**
         * 获取图片,视频,html存储路径
         * 
         * @return
         */
        @SuppressLint("DefaultLocale")
        public static String getImageStorageDir(Context context) {
            String pathStr = "";
    
            File storageDirFile = new File("/mnt/");
    
            if (storageDirFile.isDirectory()) {
    
                String[] dirList = storageDirFile.list();
    
                if (dirList != null) {
                    for (int i = 0; i < dirList.length; i++) {
                        String dirString = (dirList[i]).toLowerCase();
                        if (dirString.equals("sdcard")) {
    
                            if (ifValid("/mnt/" + dirList[i] + "/")) {
    
                                pathStr = dirList[i];
                            }
    
                        }
                    }
                }
    
            }
            if (pathStr.equals("")) {
                return getFileDir(context) + "/spid/";
            }
    
            File mFile=new File("/mnt/" + pathStr + "/spid/");
            if (!mFile.exists()) {
                mFile.mkdirs();
            }
            return "/mnt/" + pathStr + "/spid/";
        }
    }

     

    CodeUpdate.java:

    public class CodeUpdate {
    
        private String ModuleId;
        private String Version;
        private String UpdatePackName;
        private String MD5;
        private String FileSize;
    
        public String getModuleId() {
            return ModuleId;
        }
    
        public void setModuleId(String moduleId) {
            ModuleId = moduleId;
        }
    
        public String getVersion() {
            return Version;
        }
    
        public void setVersion(String version) {
            Version = version;
        }
    
        public String getUpdatePackName() {
            return UpdatePackName;
        }
    
        public void setUpdatePackName(String updatePackName) {
            UpdatePackName = updatePackName;
        }
    
        public String getMD5() {
            return MD5;
        }
    
        public void setMD5(String mD5) {
            MD5 = mD5;
        }
    
        public String getFileSize() {
            return FileSize;
        }
    
        public void setFileSize(String fileSize) {
            FileSize = fileSize;
        }
    
    }

     

    NetworkDataUpdate.java:

    /**
     * 获取网络Json数据并解析,插入本地数据库
     *
     */
    public class NetworkDataUpdate{
        
        private static NetworkDataUpdate instance;
        
        private Context context;
        //接口参数
        private String []propertyName={"datetime","clientID"};
        
        private ImageLoader imageLoader;
        private Des mDes=new Des();
        
    
        public NetworkDataUpdate(Context context){
            this.context=context;        
            imageLoader=ImageLoader.getInstance(context, MyMount.getImageStorageDir(context));
        }
        
        public static NetworkDataUpdate getInstance(Context context){
            if (instance==null) {
                instance=new NetworkDataUpdate(context);
            }
            return instance;
        }
    
      /**
         * 更新apk接口
         * @return
         */
        public CodeUpdate GetCodeUpdate(){
            String mac="";
            try {
                mac=mDes.createEncrypt(UniqueIdentifier.getInstance(context).getMac());
            } catch (UnsupportedEncodingException e1) {
                e1.printStackTrace();
            }
            String []propertyValue=new String[]{mac};
            String []propertyName=new String[]{"clientID"};
            //通过GetCodeUpdate接口,发送请求,从服务器端接收返回的json数据
            JSONObject jsonObject=UrlData2Json.getJSONObject(YContants.namespace, KeltiIntenface.FunctionName.GetCodeUpdate, KeltiIntenface.url, propertyName, propertyValue, null);
            
            
            if (jsonObject==null) {//返回数据为null
                if(YContants.DEBUG) YLogUtil.printLog("codeUpdateJsonArray为空");
                return null;
            }
            
            if(YContants.DEBUG) YLogUtil.printLog(jsonObject);
            CodeUpdate codeUpdate=null;
            
            try {
                
                if (jsonObject.getInt("State")!=1) {//程序验证不通过,则返回null
                    return null;
                }
                JSONObject childJsonObject=jsonObject.getJSONObject("Data");
                
                codeUpdate=new CodeUpdate();
                codeUpdate.setModuleId(childJsonObject.getString("ModuleId"));
                codeUpdate.setVersion(childJsonObject.getString("Version"));
                codeUpdate.setUpdatePackName(childJsonObject.getString("UpdatePackName"));
                codeUpdate.setMD5(childJsonObject.getString("MD5"));
                codeUpdate.setFileSize(childJsonObject.getString("FileSize"));
                
            } catch (JSONException e) {
                e.printStackTrace();
            }
            
            if (codeUpdate.getModuleId()!=null&&!codeUpdate.getModuleId().equals("")) {
                DataAddDB.addApk(context,"1", codeUpdate);
            }
            
            
            return codeUpdate;
            
        }
    }

     

    DataAddDB.java:

    public class DataAddDB {
    /**
         * 向Apk表插入数据
         * @param context
         * @param downloadList
         */
        public static void addApk(Context context,String appID,CodeUpdate codeUpdate){
            
            HashMap<String, Object> mHashMap=DButil2.getInstance(context).queryTableApk(appID);
            
            boolean isExist=false;//用于标记表id是否重复
            if (appID.equals(mHashMap.get(DBContants.TableApkUpdate.ID)+"")) {
                    
                isExist=true;
            }
                
            ContentValues values=new ContentValues();
            values.put(DBContants.TableApkUpdate.ID, appID+"");
            values.put(DBContants.TableApkUpdate.VERSION, codeUpdate.getVersion());
            values.put(DBContants.TableApkUpdate.UpdatePackName, codeUpdate.getUpdatePackName());
            values.put(DBContants.TableApkUpdate.MD5, codeUpdate.getMD5());
            values.put(DBContants.TableApkUpdate.FileSize, codeUpdate.getFileSize());
            
        
            if (!isExist) {
                
                DButil2.getInstance(context).addTableApkUpdate(values);
            }
            else {
                DButil2.getInstance(context).updateTableApk(values, appID+"");
            }
                
        }    
    }

     

    DButils2.java:

    public class DButil2 extends DBUtil1{
    
        //volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。用于多线程访问,看作程度较轻的 synchronized
        private volatile static DButil2 instance;
         
        private DButil2(Context context){
            super(context);
            
        }
         
        public static DButil2 getInstance(Context context){
            ifReadCount=0;
            if(instance==null){
             
                synchronized(DButil2.class){
                 
                    if(instance==null){
                     
                        instance=new DButil2(context);
                     
                    }
             
                }
         
            }
         
        return instance;
         
        }
    //*****************************************************apk更新************************************************
        public HashMap<String, Object>queryTableApk(String appID){
            Cursor cursor = db.rawQuery("select * from apkUpdate where Id=?",new String[]{appID+""});
            
            return queryTableApk(cursor);
        }
    
    }

     

    DButil1.java:

    public class DBUtil1 extends RootDBUtil {
    
        private volatile static DBUtil1 instance;
        
        protected DBUtil1(Context context) {
            super(context);
            
        }
        
        public static  DBUtil1 getInstance(Context context){
            if(instance==null){
                 
                synchronized(DBUtil1.class){
                 
                    if(instance==null){
                     
                        instance=new DBUtil1(context);
                     
                    }
             
                }
         
            }
            return instance;
        }
    
    /**
         * 查询apk表
         * @param cursor
         * @return
         */
        public HashMap<String, Object>queryTableApk(Cursor cursor){
            HashMap<String, Object>mHashMap=new HashMap<String, Object>();
            try {
                while (cursor.moveToNext()) {
                    mHashMap.put(DBContants.TableApkUpdate.ID, cursor.getString(0));
                    mHashMap.put(DBContants.TableApkUpdate.VERSION, cursor.getString(1));
                    mHashMap.put(DBContants.TableApkUpdate.UpdatePackName, cursor.getString(2));
                    mHashMap.put(DBContants.TableApkUpdate.MD5, cursor.getString(3));
                    mHashMap.put(DBContants.TableApkUpdate.FileSize, cursor.getString(4));
                    
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if (!cursor.isClosed()) {
                    cursor.close();
                }
            }
            return mHashMap;
        }
    
    }

     

    RootDBUtil.java:

    public class RootDBUtil {
    
        private volatile static RootDBUtil instance;
    
        SQLiteDatabase db;
    
        protected RootDBUtil(Context context) {
            
            db = new DBHelper(context).getWritableDatabase();
                    
            
        }
    
        
        public static  RootDBUtil getInstance(Context context) {
            if(instance==null){
                 
                synchronized(RootDBUtil.class){
                 
                    if(instance==null){
                     
                        instance=new RootDBUtil(context);
                     
                    }
             
                }
         
            }
            return instance;
        }
    
    //******************************************************apk更新*******************************************************
        public synchronized void addTableApkUpdate(ContentValues values){
            try {
                db.insert(DBContants.TableApkUpdate.TABLE_NAME, null, values);
            } catch (Exception e) {
                e.printStackTrace();
            }
        
        }
        
        public synchronized void updateTableApk(ContentValues values,String id){
            try {
                db.update(DBContants.TableApkUpdate.TABLE_NAME, values, DBContants.TableApkUpdate.ID + " = ? ", new String[] { id });
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }

     

    DBHelper.java:

    public class DBHelper extends SQLiteOpenHelper {
        /**
         * 数据库版本
         */
        private static final int VERSION = 1;
        /**
         * 数据库名称
         */
        public static final String NAME = "spidclient.db";
    
        private Context context;
        /**
         * 
         * @param name
         *             数据库文件名
         * @param factory
         *            游标工厂
         * @param version
         *            数据库版本,最小值为1
         */
        public DBHelper(Context context) {
            super(context, NAME, null, VERSION);
            this.context=context;
        }
    
        /**
         * 第一次创建数据库的时候调用
         */
        public void onCreate(SQLiteDatabase db) {
    
            /**
             * 
             * create table t_contact(id integer primary key autoincrement, name
             * text, photo integer, phone text, address text, email text, pin_yin
             * text);
             * 
             */
            
            
            
            createUpdateApk(db);
            
            
        }
    
        /**
         * 当数据库版本改变的时候调用
         */
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub
            
        }
      /**
         * 更新apk
         * @param db
         */
        private void createUpdateApk(SQLiteDatabase db){
    
            StringBuilder sb = new StringBuilder(" create table ").append(DBContants.TableApkUpdate.TABLE_NAME).append("(")//                
                    .append(DBContants.TableApkUpdate.ID).append(" Integer primary key autoincrement,")//
                    .append(DBContants.TableApkUpdate.VERSION).append(" Integer, ")//
                    .append(DBContants.TableApkUpdate.UpdatePackName).append(" text, ")//
                    .append(DBContants.TableApkUpdate.MD5).append(" text, ")//
                    .append(DBContants.TableApkUpdate.FileSize).append(" text); ");
            //执行创表语句
            db.execSQL(sb.toString());
        
        }
    }

     

    DBContants.java:

    public class DBContants {
      //apk更新表
        public static class TableApkUpdate{
            public static final String TABLE_NAME="apkUpdate";
            public static final String ID="Id";
            public static final String VERSION="Version";
            public static final String UpdatePackName="UpdatePackName";
            public static final String MD5="MD5";
            public static final String FileSize="FileSize";
        
        }
    }

     

    KeltiIntenface.java:

    public class KeltiIntenface {
        public static String ipStr="newkelti.ip24.com.cn";
        public static String postStr="860";
    

        //程序更新接口
        public static String url="http://"+ipStr+":"+postStr+"/WebService/Pad_DataUpdate.asmx";

      public static class FunctionName{
         //更新apk
            public static String GetCodeUpdate="GetCodeUpdate_v01";//"GetCodeUpdate";
      }
    
    }

     

    YContants.java:

    public class YContants {
            // 命名空间
        public static String namespace = "http://tempuri.org/";
    }

     

    Des.java:

    
    

    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import android.annotation.SuppressLint;
    import android.util.Base64;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;



    /**
    * 解密 */ public class Des {

     private Cipher c; // 密码器

      private byte[] cipherByte;
      private SecretKey deskey; // 密钥

      private String keyString = "A3F2569DESJEIWBCJOTY45DYQWF68H1Y"; // 获得密钥的参数

    
      /**
         * 加密
         * @param data
         * @return
         * @throws UnsupportedEncodingException
         */
        public String createEncrypt(String data)
                throws UnsupportedEncodingException {
            if (data.equals("")) {
                return "";
            }
    
            try {
    
                byte[] buffData = data.getBytes("UTF8");
    
                byte[] dKey = deBase64(keyString);
                deskey = new javax.crypto.spec.SecretKeySpec(dKey, Algorithm);
    
                try {
                    c = Cipher.getInstance(Algorithm);
                } catch (Exception e) {
    
                    e.printStackTrace();
                }
    
                c.init(Cipher.ENCRYPT_MODE, deskey);
    
                cipherByte = c.doFinal(buffData);
    
            } catch (java.security.InvalidKeyException ex) {
                ex.printStackTrace();
            } catch (javax.crypto.BadPaddingException ex) {
                ex.printStackTrace();
            } catch (javax.crypto.IllegalBlockSizeException ex) {
                ex.printStackTrace();
            } catch (IOException e) {
    
                e.printStackTrace();
            }
    
            return Base64.encodeToString(cipherByte, Base64.DEFAULT);
        }
    }

     

    UrlData2Json.java:

    /**
     * 获取接口Json数据
     *
     */
    public class UrlData2Json {
    
        /**
         * 返回一个JSONObject对象
         * 
         * 说明:参数名数组和参数值数组要一一对应
         * 
         * @param namespace 命名空间
         * @param methoName 方法名
         * @param url 接口地址
         * @param propertyName 参数名数组
         * @param propertyValue 参数值数组
         * @param networkExceptionListener 监听器
         * @return
         */
        public static JSONObject getJSONObject(String namespace, String methoName,
                String url, String []propertyName,
                Object[] propertyValue,YNetworkExceptionListener networkExceptionListener) {
    
            
    
            try {
                SoapObject soapObject = new SoapObject(namespace, methoName);
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                        SoapEnvelope.VER11);
    
                if (propertyName!=null&&propertyValue!=null) {
                    for (int i = 0; i < propertyName.length; i++) {
                        // 带参数的方法调用,若调用无参数的,则无需此句
                        soapObject.addProperty(propertyName[i],propertyValue[i]);// 添加参数
    
                    }
                }
                
                envelope.dotNet = true;
                envelope.setOutputSoapObject(soapObject);
                HttpTransportSE httpTranstation = new HttpTransportSE(url,YContants.CONNECTION_TIME);
                httpTranstation.call(namespace + methoName, envelope);
                
                Object result = envelope.getResponse();
                
                if (null==result) {
                    return new JSONObject();
                }
                String str = (String) result.toString();// 获得请求的字符串
    
                JSONObject jObject = new JSONObject(str);
                
    
                return jObject;
                
            } 
            catch(ConnectException connectException){
                if (networkExceptionListener!=null) {
                    networkExceptionListener.networkException();
                    
                }
                connectException.printStackTrace();
                if(YContants.DEBUG) YLogUtil.printLog("connectException");
            }
            catch (SocketTimeoutException  socketTimeoutException) {
                if (networkExceptionListener!=null) {
                    networkExceptionListener.connectionTimeOut();
                    
                }
                socketTimeoutException.printStackTrace();
                if(YContants.DEBUG) YLogUtil.printLog("socketTimeoutException");
            }
            catch (JSONException e) {        
                if (networkExceptionListener!=null) {
                    networkExceptionListener.JSONException();
                    
                }
                e.printStackTrace();
                if(YContants.DEBUG) YLogUtil.printLog("JSONException");
            }
            
            catch (Exception e) {
                if (networkExceptionListener!=null) {
                    networkExceptionListener.otherException();
                }
                e.printStackTrace();
                if(YContants.DEBUG) YLogUtil.printLog("Exception");
                
            }        
            return null;
    
        }
    }

     

    VersionUtil.java:

    import android.content.Context;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageManager.NameNotFoundException;
    
    public class VersionUtil {
    
        public static String getVersionCode(Context context) {
    
            String version = "1.0";
            try {
                // 获取packagemanager的实例
                PackageManager packageManager = context.getPackageManager();
                // getPackageName()是你当前类的包名,0代表是获取版本信息
                PackageInfo packInfo;
                packInfo = packageManager.getPackageInfo(context.getPackageName(),
                        0);
                version = packInfo.versionName;
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
    
            return version;
        }
    }

     

    DecompressionZip.java:

    
    

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.util.Enumeration;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipException;
    import java.util.zip.ZipFile;


    /**
    * 解压ZIP文件 * */ public class DecompressionZip { /** * 解压功能 * 将zipFile文件解压到folderPath目录 * * @param zipFile 压缩文件 * @param folderPath 存储路径 * @return * @throws ZipException * @throws IOException */ @SuppressWarnings("rawtypes") public static int upZipFile(File zipFile, String folderPath) throws ZipException, IOException { ZipFile zfile = new ZipFile(zipFile); Enumeration zList = zfile.entries();//压缩文件的条目 ZipEntry ze = null; byte[] buf = new byte[1024]; while (zList.hasMoreElements()) { ze = (ZipEntry) zList.nextElement(); if (ze.isDirectory()) {//判断是否为一个目录 String dirstr = folderPath + ze.getName(); dirstr = new String(dirstr.getBytes("8859_1"), "GB2312"); File f = new File(dirstr); f.mkdir(); continue; } OutputStream os = new BufferedOutputStream(new FileOutputStream( getRealFileName(folderPath, ze.getName()))); InputStream is = new BufferedInputStream(zfile.getInputStream(ze)); int readLen = 0; while ((readLen = is.read(buf, 0, 1024)) != -1) { os.write(buf, 0, readLen); } is.close(); os.close(); } zfile.close(); return 0; } }

     

    YLogUtil.java:

    /**
     * 打印log
     *
     */
    public class YLogUtil {
    
    private static final boolean LOG_DEBUG = true;//log输出的开关
    public static <T> void printSpidLog(T log) { if(LOG_DEBUG){ String logText=""; try { String lineFormat = "类名:%s---方法名:%s---第%d行"; StackTraceElement traceElement = Thread.currentThread().getStackTrace()[3]; logText = String.format(lineFormat, traceElement.getFileName(), traceElement.getMethodName(), traceElement.getLineNumber()); } catch (Exception e) { e.printStackTrace(); logText="找不到出错位置"; } Log.i("spid",logText+"---信息:"+log); } } }

     

    转载于:https://www.cnblogs.com/wangchaozhangshu/p/5546002.html

    展开全文
  • 面试中经常会问到Android 中SQLite 数据库版本更新问题,我们需要怎样去回答呢? 下面是本人的一些认识,仅供参考。 当你创建一个类并继承SqliteOpenHelper时,会要求你实现他的两个回调方法:onCreate()和...
  • Android Studio——版本自动更新详解

    千次阅读 2017-03-07 11:52:59
    有些时候总是会报一些Android Studio vesion 版本低,要求升级之类的错误,然而大家又会嫌麻烦去网上下载,今天给大家介绍的一个小技巧是,在Android Studio里面直接就能升级的小方法,我们来看看怎样升级;...
  • ANDROID系统的版本众多,更新频繁。有时候我们需要在运行时来判断所运行的ANDROID系统版本以确定使用什么API,比如从ANDROID 2.0开始才支持多点触摸。 那么,怎样在程序中来判断ANDROID系统的版本号也即API ...
  • Android 实现通知栏通知APP版本更新

    千次阅读 2017-05-13 21:35:44
    我们似乎在做什么apk,都需要去做更新这个功能,那怎么去做这个功能才好呢,那当然在做的时候当然回去百度一下(除非是大神)。想我这个种没做一个比较好玩的功能的时候,第一步就是去百度大家的做法,想法。怎么去...
  • Android studio更新

    2016-04-11 22:32:52
    快速自动更新Android Studio版本  在开发过程中,有些时候总是会报一些Android Studio vesion 版本低,要求升级之类的错误,然而大家又会嫌麻烦去网上下载,今天给大家介绍的一个小技巧是,在Android Studio...
  • flutter 更新应用版本

    千次阅读 2019-02-23 12:20:00
    前面已经提到过 怎样修改版本号。 做过移动开发的小伙伴应该知道 这是一个本地版本。运行版本。和线上版本三者比对逻辑过程 这里就不多说了。 我们现在使用flutter更新版本 Android: 下载新版本包 ios:跳转...
  • 快速自动更新Android Studio版本  在开发过程中,有些时候总是会报一些Android Studio vesion 版本低,要求升级之类的错误,然而大家又会嫌麻烦去网上下载,今天给大家介绍的一个小技巧是,在Android Studio...
  • 一个良好的Android程序都应该有版本更新,那怎样实现更新呢?今天就为大家介绍应用自动更新的全过程。 程序自动更新的流程大致如下: 程序启动 -> 适时后台检查更新 -> 链接远程服务器 -> 获取新版本信息 ...
  • 当最新的Android版本号为你的应用提供着非常棒的APIs时。你却要在很多其它的设备更新之前继续支持老的系统版本号。这篇课程怎样在继续支持低版本号的系统的情况下使用新版本号的高级API。 Platform Versions仪表...
  • 开发一个android应用程序,必须有的一个功能就是更新应用的版本。 那么点击更新版本的控件后,应该如何调出apk的安装界面呢? /** * 安装程序 * * @param context 上下文 * @param file apk的保存...
  • 应用都有版本更新,那么怎样实现更新呢?今天就为大家介绍应用自动更新的全过程。 程序自动更新的流程大致如下: 程序启动 -->适时后台检查更新--->链接远程服务器-->获取新版本信息 -->比对当前...
  • ANDROID系统的版本众多,更新频繁。有时候我们需要在运行时来判断所运行的ANDROID系统版本以确定使用什么API,比如从ANDROID 2.0开始才支持多点触摸。   那么,怎样在程序中来判断ANDROID系统的版本号也即API ...
  • 一个良好的android 程序都应该有版本更新,那怎样实现更新呢?今天就为大家介绍应用自动更新 的全过程。 程序 自动更新 的流程大致如下: 程序启动 -> 适时后台检查更新 -> 链接远程服务器 -> 获取新版本...
  • 因为最新的系统往往是为最新款的手机“量身定制”的,特别是iPhone 用户应该更有感触。但是不想升级又总是收到提醒,真的很烦人有木有!今天绿豆就教你彻底解决,iPhone和...iOS 11以下版本的系统更新包删除步骤,进...
  • 最近在做毕设,里面牵涉到版本更新,当有新版本时可以下载新版本,下载完成之后提示安装。那么怎么实现下载完成之后提示安装呢?
  • Android Studio的优点之一就是更新迭代速度很快。每次新版发布都会带来一系列的新功能、新工具,并修复一堆Bug,所有这些都能提高用户的生产率。想要尝试新功能,却不想冒险替换掉当前稳定的开发环境?那么应该采取...
  • Android断点续传文件下载,简单实用的代码,如需要可参考。 希望不要觉得我又造一个轮子,我先用了网上代码觉得不好使用,而且发现有错误; 有一些功能强大的框架,我懒得去了解,去学习怎样使用它也要花时间; ...

空空如也

空空如也

1 2 3 4 5
收藏数 86
精华内容 34
关键字:

怎样更新android版本