精华内容
下载资源
问答
  • 在iOS开发过程中,App上线之后,进行版本更新的时候,需要及时提醒用户更新最新的App版本,那么就用到了版本更新提示框的使用。本章就来介绍一下App版本更新提示框的使用方法,各取所需,仅供参考。 一、根据第三方...

           今天五一国际劳动节,依然在正常上班,就分享一个知识点呗。在iOS开发过程中,App上线之后,进行版本更新的时候,需要及时提醒用户更新最新的App版本,那么就用到了版本更新提示框的使用。本章就来介绍一下App版本更新提示框的使用方法,各取所需,仅供参考。

    一、根据第三方实现版本更新提示框的方法

            根据第三方实现App版本更新提示框,进行了封装,然后直接将AppID作为参数传进去或者直接获取应用的bundleID来使用的,把工具类拖入到项目中,只需要Appdelegate文件里面一句代码就可集成实现的方法。原创的下载链接https://github.com/emotality/ATAppUpdater 具体实现操作步骤如下所示:

    1、AppUpdater.h文件:

    #import <UIKit/UIKit.h>

    #import <SystemConfiguration/SystemConfiguration.h>

     

    @interface AppUpdater : NSObject <UIAlertViewDelegate>

    + (id)sharedUpdater;

    - (void)showUpdateWithForce;

    - (void)showUpdateWithConfirmation;

    - (void)forceOpenNewAppVersion:(BOOL)force

    __attrib

    展开全文
  • Android提示版本更新

    万次阅读 多人点赞 2014-05-07 10:43:10
    如果不是最新版,提示更新 正在下载 安装新程序        一、准备知识  在AndroidManifest.xml里定义了每个Android apk的版本标识: package="com.example.try_downloadfile_progress" ...

    前言:在软件开发的尾声应该都会遇到这个问题,还好网上资料很多,所以基本不费什么力气就搞定了,现记录于下。这里用的PHP服务器。

     效果图:(PHP服务器)

                       初始界面                      检测后,如果已是最新版

                                            

    如果不是最新版,提示更新                  正在下载                             安装新程序    

         

     一、准备知识

     在AndroidManifest.xml里定义了每个Android apk的版本标识:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.try_downloadfile_progress"
        android:versionCode="1"
        android:versionName="1.0" >

    其中,android:versionCode和android:versionName两个字段分别表示版本代码,版本名称。versionCode是整型数字,versionName是字符串。由于version是给用户看的,不太容易比较大小,升级检查时,可以以检查versionCode为主,方便比较出版本的前后大小。
    那么,在应用中如何读取AndroidManifest.xml中的versionCode和versionName呢?可以使用PackageManager的API,参考以下代码:

    	/**
    	 * 获取软件版本号
    	 * @param context
    	 * @return
    	 */
    	public static int getVerCode(Context context) {
            int verCode = -1;
            try {
            	//注意:"com.example.try_downloadfile_progress"对应AndroidManifest.xml里的package="……"部分
                verCode = context.getPackageManager().getPackageInfo(
                        "com.example.try_downloadfile_progress", 0).versionCode;
            } catch (NameNotFoundException e) {
            	Log.e("msg",e.getMessage());
            }
            return verCode;
        }
       /**
        * 获取版本名称
        * @param context
        * @return
        */
        public static String getVerName(Context context) {
            String verName = "";
            try {
                verName = context.getPackageManager().getPackageInfo(
                        "com.example.try_downloadfile_progress", 0).versionName;
            } catch (NameNotFoundException e) {
            	Log.e("msg",e.getMessage());
            }
            return verName;   
    }

    这里要注意一个地方:代码里的“com.example.try_downloadfile_progress”对应AndroidManifest.xml里的package="……"部分

    二、XML代码 

     XML代码非常简单,就是如初始化界面那样,在里面加一个BUTTON而已。代码如下:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        tools:context=".MainActivity" >
    
        <Button 
            android:id="@+id/chek_newest_version"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dip"
            android:text="检测最新版本"/>
    
    </RelativeLayout>

    三、辅助类构建(Common)

     这里为了开发方便,将一些公共的函数,单独放在Common类中实现,代码如下:

    package com.example.try_downloadfile_progress;
    /**
     * @author harvic
     * @date 2014-5-7
     * @address http://blog.csdn.net/harvic880925
     */
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.List;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.protocol.HTTP;
    
    import android.content.Context;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.util.Log;
    
    public class Common {
    	public static final String SERVER_IP="http://192.168.1.105/";
    	public static final String SERVER_ADDRESS=SERVER_IP+"try_downloadFile_progress_server/index.php";//软件更新包地址
    	public static final String UPDATESOFTADDRESS=SERVER_IP+"try_downloadFile_progress_server/update_pakage/baidu.apk";//软件更新包地址
    
    	/**
    	 * 向服务器发送查询请求,返回查到的StringBuilder类型数据
    	 * 
    	 * @param ArrayList
    	 *            <NameValuePair> vps POST进来的参值对
    	 * @return StringBuilder builder 返回查到的结果
    	 * @throws Exception
    	 */
    	public static StringBuilder post_to_server(List<NameValuePair> vps) {
    		DefaultHttpClient httpclient = new DefaultHttpClient();
    		try {
    			HttpResponse response = null;
    			// 创建httpost.访问本地服务器网址
    			HttpPost httpost = new HttpPost(SERVER_ADDRESS);
    			StringBuilder builder = new StringBuilder();
    
    			httpost.setEntity(new UrlEncodedFormEntity(vps, HTTP.UTF_8));
    			response = httpclient.execute(httpost); // 执行
    
    			if (response.getEntity() != null) {
    				// 如果服务器端JSON没写对,这句是会出异常,是执行不过去的
    				BufferedReader reader = new BufferedReader(
    						new InputStreamReader(response.getEntity().getContent()));
    				String s = reader.readLine();
    				for (; s != null; s = reader.readLine()) {
    					builder.append(s);
    				}
    			}
    			return builder;
    
    		} catch (Exception e) {
    			// TODO: handle exception
    			Log.e("msg",e.getMessage());
    			return null;
    		} finally {
    			try {
    				httpclient.getConnectionManager().shutdown();// 关闭连接
    				// 这两种释放连接的方法都可以
    			} catch (Exception e) {
    				// TODO Auto-generated catch block
    				Log.e("msg",e.getMessage());
    			}
    		}
    	}
    	
    	/**
    	 * 获取软件版本号
    	 * @param context
    	 * @return
    	 */
    	public static int getVerCode(Context context) {
            int verCode = -1;
            try {
            	//注意:"com.example.try_downloadfile_progress"对应AndroidManifest.xml里的package="……"部分
                verCode = context.getPackageManager().getPackageInfo(
                        "com.example.try_downloadfile_progress", 0).versionCode;
            } catch (NameNotFoundException e) {
            	Log.e("msg",e.getMessage());
            }
            return verCode;
        }
       /**
        * 获取版本名称
        * @param context
        * @return
        */
        public static String getVerName(Context context) {
            String verName = "";
            try {
                verName = context.getPackageManager().getPackageInfo(
                        "com.example.try_downloadfile_progress", 0).versionName;
            } catch (NameNotFoundException e) {
            	Log.e("msg",e.getMessage());
            }
            return verName;   
    }	
    	
    }


    这里除了上面我们提到的两个函数getVerCode和getVerName外,还有几个常量和一个函数定义,含义分别如下:

    SERVER_IP:服务器IP地址(大家在拿到试验的时候,要改成自己服务器IP地址) 
    SERVER_ADDRESS:android程序要将请求发送到的页面地址,无须更改。
    UPDATESOFTADDRESS:更新安装包存放的位置,无须更改。

     函数StringBuilder post_to_server(List<NameValuePair> vps)是访问服务器并返回结果的功能封装。传进去名值对,返回StringBuilder对象

     四、主页面代码构建

     1、首先设置AndroidManifest.xml,使其能访问网络和SD卡

    在</manifest>标签上面,加入:

    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >
    </uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
    </uses-permission>

    2、主页代码:

    先贴出全部代码,然后逐步讲解,全部代码如下:

    package com.example.try_downloadfile_progress;
    /**
     * @author harvic
     * @date 2014-5-7
     * @address http://blog.csdn.net/harvic880925
     */
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.message.BasicNameValuePair;
    import org.json.JSONArray;
    
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.Dialog;
    import android.app.ProgressDialog;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    
    public class MainActivity extends Activity {
    
    	Button m_btnCheckNewestVersion;
    	long m_newVerCode; //最新版的版本号
    	String m_newVerName; //最新版的版本名
    	String m_appNameStr; //下载到本地要给这个APP命的名字
    	
    	Handler m_mainHandler;
    	ProgressDialog m_progressDlg;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		//初始化相关变量
    		initVariable();
    		
    		m_btnCheckNewestVersion.setOnClickListener(btnClickListener);
    	}
    	private void initVariable()
    	{
    		m_btnCheckNewestVersion = (Button)findViewById(R.id.chek_newest_version);
    		m_mainHandler = new Handler();
    		m_progressDlg =  new ProgressDialog(this);
    		m_progressDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    		 // 设置ProgressDialog 的进度条是否不明确 false 就是不设置为不明确     
    		m_progressDlg.setIndeterminate(false);    
    		m_appNameStr = "haha.apk";
    	}
    	
    	OnClickListener btnClickListener = new View.OnClickListener() {
    		
    		@Override
    		public void onClick(View v) {
    			// TODO Auto-generated method stub
    			new checkNewestVersionAsyncTask().execute();
    		}
    	};
    	
    	class checkNewestVersionAsyncTask extends AsyncTask<Void, Void, Boolean>
    	{
    
    		@Override
    		protected Boolean doInBackground(Void... params) {
    			// TODO Auto-generated method stub
    			if(postCheckNewestVersionCommand2Server())
    			{
    				int vercode = Common.getVerCode(getApplicationContext()); // 用到前面第一节写的方法  
    		         if (m_newVerCode > vercode) {  
    		             return true;
    		         } else {  
    		             return false;
    		         }  
    			}
    			return false;
    		}
    		
    		@Override
    		protected void onPostExecute(Boolean result) {
    			// TODO Auto-generated method stub
    			if (result) {//如果有最新版本
    				doNewVersionUpdate(); // 更新新版本  
    			}else {
    				notNewVersionDlgShow(); // 提示当前为最新版本  
    			}
    			super.onPostExecute(result);
    		}
    		
    		@Override
    		protected void onPreExecute() {
    			// TODO Auto-generated method stub
    			super.onPreExecute();
    		}
    	}
    	
    	/**
    	 * 从服务器获取当前最新版本号,如果成功返回TURE,如果失败,返回FALSE
    	 * @return
    	 */
    	private Boolean postCheckNewestVersionCommand2Server()
    	{
    		StringBuilder builder = new StringBuilder();
    		JSONArray jsonArray = null;
    		try {
    			// 构造POST方法的{name:value} 参数对
    			List<NameValuePair> vps = new ArrayList<NameValuePair>();
    			// 将参数传入post方法中
    			vps.add(new BasicNameValuePair("action", "checkNewestVersion"));
    			builder = Common.post_to_server(vps);
    			jsonArray = new JSONArray(builder.toString());
    			if (jsonArray.length()>0) {
    				if (jsonArray.getJSONObject(0).getInt("id") == 1) {
    					m_newVerName = jsonArray.getJSONObject(0).getString("verName");
    					m_newVerCode = jsonArray.getJSONObject(0).getLong("verCode");
    					
    					return true;
    				}
    			}
    	
    			return false;
    		} catch (Exception e) {
    			Log.e("msg",e.getMessage());
    			m_newVerName="";
    			m_newVerCode=-1;
    			return false;
    		}
    	}
    	
    	/**
    	 * 提示更新新版本
    	 */
    		private void doNewVersionUpdate() {
    			int verCode = Common.getVerCode(getApplicationContext());  
    		    String verName = Common.getVerName(getApplicationContext());  
    		    
    		    String str= "当前版本:"+verName+" Code:"+verCode+" ,发现新版本:"+m_newVerName+
    		    		" Code:"+m_newVerCode+" ,是否更新?";  
    		    Dialog dialog = new AlertDialog.Builder(this).setTitle("软件更新").setMessage(str)  
    		            // 设置内容  
    		            .setPositiveButton("更新",// 设置确定按钮  
    		                    new DialogInterface.OnClickListener() {  
    		                        @Override  
    		                        public void onClick(DialogInterface dialog,  
    		                                int which) { 
    		                            m_progressDlg.setTitle("正在下载");  
    		                            m_progressDlg.setMessage("请稍候...");  
    		                            downFile(Common.UPDATESOFTADDRESS);  //开始下载
    		                        }  
    		                    })  
    		            .setNegativeButton("暂不更新",  
    		                    new DialogInterface.OnClickListener() {  
    		                        public void onClick(DialogInterface dialog,  
    		                                int whichButton) {  
    		                            // 点击"取消"按钮之后退出程序  
    		                            finish();  
    		                        }  
    		                    }).create();// 创建  
    		    // 显示对话框  
    		    dialog.show();  
    		}
    		/**
    		 *  提示当前为最新版本  
    		 */
    		private void notNewVersionDlgShow()
    		{
    			int verCode = Common.getVerCode(this);  
    		    String verName = Common.getVerName(this); 
    		    String str="当前版本:"+verName+" Code:"+verCode+",/n已是最新版,无需更新!";
    		    Dialog dialog = new AlertDialog.Builder(this).setTitle("软件更新")  
    		            .setMessage(str)// 设置内容  
    		            .setPositiveButton("确定",// 设置确定按钮  
    		                    new DialogInterface.OnClickListener() {  
    		                        @Override  
    		                        public void onClick(DialogInterface dialog,  
    		                                int which) {  
    		                            finish();  
    		                        }  
    		                    }).create();// 创建  
    		    // 显示对话框  
    		    dialog.show();  
    		}
    		private void downFile(final String url)
    		{
    			m_progressDlg.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();  
    		                
    		                m_progressDlg.setMax((int)length);//设置进度条的最大值
    		                
    		                InputStream is = entity.getContent();  
    		                FileOutputStream fileOutputStream = null;  
    		                if (is != null) {  
    		                    File file = new File(  
    		                            Environment.getExternalStorageDirectory(),  
    		                            m_appNameStr);  
    		                    fileOutputStream = new FileOutputStream(file);  
    		                    byte[] buf = new byte[1024];  
    		                    int ch = -1;  
    		                    int count = 0;  
    		                    while ((ch = is.read(buf)) != -1) {  
    		                        fileOutputStream.write(buf, 0, ch);  
    		                        count += ch;  
    		                        if (length > 0) {  
    		                        	 m_progressDlg.setProgress(count);
    		                        }  
    		                    }  
    		                }  
    		                fileOutputStream.flush();  
    		                if (fileOutputStream != null) {  
    		                    fileOutputStream.close();  
    		                }  
    		                down();  
    		            } catch (ClientProtocolException e) {  
    		                e.printStackTrace();  
    		            } catch (IOException e) {  
    		                e.printStackTrace();  
    		            }  
    		        }  
    		    }.start();  
    		}
    		private void down() {
    	        m_mainHandler.post(new Runnable() {
    	            public void run() {
    	                m_progressDlg.cancel();
    	                update();
    	            }
    	        });
    	}
    		
    	    void update() {
    	        Intent intent = new Intent(Intent.ACTION_VIEW);
    	        intent.setDataAndType(Uri.fromFile(new File(Environment
    	                .getExternalStorageDirectory(), m_appNameStr)),
    	                "application/vnd.android.package-archive");
    	        startActivity(intent);
    	    }
    
    
    }
    
    逐步讲解:

    1、OnCreate函数:

    先从主函数开始讲,OnCreate函数中只有两部分,一个是initVariable()初始化变量,这个不多说,难度不大;第二个是为版本检测按钮设置监听函数——btnClickListener,而在btnClickListener函数中可以明显的看到,其中也只有一个类checkNewestVersionAsyncTask,这里采用异步方式处理更新问题。下面看checkNewestVersionAsyncTask函数

    2、checkNewestVersionAsyncTask函数

    class checkNewestVersionAsyncTask extends AsyncTask<Void, Void, Boolean>
    {
    
    	@Override
    	protected Boolean doInBackground(Void... params) {
    		// TODO Auto-generated method stub
    		if(postCheckNewestVersionCommand2Server())
    		{
    			int vercode = Common.getVerCode(getApplicationContext()); // 用到前面第一节写的方法  
    	         if (m_newVerCode > vercode) {  
    	             return true;
    	         } else {  
    	             return false;
    	         }  
    		}
    		return false;
    	}
    	
    	@Override
    	protected void onPostExecute(Boolean result) {
    		// TODO Auto-generated method stub
    		if (result) {//如果有最新版本
    			doNewVersionUpdate(); // 更新新版本  
    		}else {
    			notNewVersionDlgShow(); // 提示当前为最新版本  
    		}
    		super.onPostExecute(result);
    	}
    	
    	@Override
    	protected void onPreExecute() {
    		// TODO Auto-generated method stub
    		super.onPreExecute();
    	}
    }

    (1)首先看后台操作doInBackground

    首先利用postCheckNewestVersionCommand2Server()函数将请求发送到服务器,该函数根据是否请求成功返回TRUE或FALSE,然后将从服务器上获取的版本代码与本地的版本代码进行比较,如果要更新返回TRUE,如果不要更新返回FASLE。

    下面看看postCheckNewestVersionCommand2Server()的代码:

    private Boolean postCheckNewestVersionCommand2Server()
    {
    	StringBuilder builder = new StringBuilder();
    	JSONArray jsonArray = null;
    	try {
    		// 构造POST方法的{name:value} 参数对
    		List<NameValuePair> vps = new ArrayList<NameValuePair>();
    		// 将参数传入post方法中
    		vps.add(new BasicNameValuePair("action", "checkNewestVersion"));
    		builder = Common.post_to_server(vps);
    		jsonArray = new JSONArray(builder.toString());
    		if (jsonArray.length()>0) {
    			if (jsonArray.getJSONObject(0).getInt("id") == 1) {
    				m_newVerName = jsonArray.getJSONObject(0).getString("verName");
    				m_newVerCode = jsonArray.getJSONObject(0).getLong("verCode");
    				
    				return true;
    			}
    		}
    
    		return false;
    	} catch (Exception e) {
    		Log.e("msg",e.getMessage());
    		m_newVerName="";
    		m_newVerCode=-1;
    		return false;
    	}
    }

    这里就是构建名值对,然后发向服务器,如果获取到了值就返回TURE,如果没获取到值,就返回FALSE。服务器返回的JSON值为:

    [{"id":"1","verName":"1.0.1","verCode":"2"}]

    对于服务器代码,由于是用PHP写的,这里就不再列出了,在源码里有。

    (2)onPostExecute()
    继续第一部分,在doInBackground操作完成后,如果需要更新doInBackground返回TRUE,否则返回FASLE,所以在onPostExecute
    中根据result不同调用不同的函数,利用doNewVersionUpdate(); 提示用户更新最新版本。利用notNewVersionDlgShow(); /提示用户当前即为最新版本,无需更新。

    对于notNewVersionDlgShow()函数仅仅是创建了个对话框,没什么实体内容,就不再具体讲解。下面具体讲述doNewVersionUpdate()下载,更新与安装程序的过程。

    3、doNewVersionUpdate()提示版本更新
    具体代码如下:

    private void doNewVersionUpdate() {
    	int verCode = Common.getVerCode(getApplicationContext());  
        String verName = Common.getVerName(getApplicationContext());  
        
        String str= "当前版本:"+verName+" Code:"+verCode+" ,发现新版本:"+m_newVerName+
        		" Code:"+m_newVerCode+" ,是否更新?";  
        Dialog dialog = new AlertDialog.Builder(this).setTitle("软件更新").setMessage(str)  
                // 设置内容  
                .setPositiveButton("更新",// 设置确定按钮  
                        new DialogInterface.OnClickListener() {  
                            @Override  
                            public void onClick(DialogInterface dialog,  
                                    int which) { 
                                m_progressDlg.setTitle("正在下载");  
                                m_progressDlg.setMessage("请稍候...");  
                                downFile(Common.UPDATESOFTADDRESS);  //开始下载
                            }  
                        })  
                .setNegativeButton("暂不更新",  
                        new DialogInterface.OnClickListener() {  
                            public void onClick(DialogInterface dialog,  
                                    int whichButton) {  
                                // 点击"取消"按钮之后退出程序  
                                finish();  
                            }  
                        }).create();// 创建  
        // 显示对话框  
        dialog.show();  
    }

    这里创建一个具有确定按钮和取消按钮功能的对话框,如果用户点击取消按钮,会利用finish()结束掉程序运行;如果点击确定按钮,则利用 downFile(Common.UPDATESOFTADDRESS); 函数开始程序下载,其中downFile()函数传进去的参数是APP所在的服务器地址。注意这里的地址要具体到下载文件,比如这里是http://192.168.1.105/server/XXX.apk

    4、downFile(final String url)下载并显示进度

    具体代码如下:

    private void downFile(final String url)
    {
    	m_progressDlg.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();  
                    
                    m_progressDlg.setMax((int)length);//设置进度条的最大值
                    
                    InputStream is = entity.getContent();  
                    FileOutputStream fileOutputStream = null;  
                    if (is != null) {  
                        File file = new File(  
                                Environment.getExternalStorageDirectory(),  
                                m_appNameStr);  
                        fileOutputStream = new FileOutputStream(file);  
                        byte[] buf = new byte[1024];  
                        int ch = -1;  
                        int count = 0;  
                        while ((ch = is.read(buf)) != -1) {  
                            fileOutputStream.write(buf, 0, ch);  
                            count += ch;  
                            if (length > 0) {  
                            	 m_progressDlg.setProgress(count);//设置当前进度
                            }  
                        }  
                    }  
                    fileOutputStream.flush();  
                    if (fileOutputStream != null) {  
                        fileOutputStream.close();  
                    }  
                    down();  //告诉HANDER已经下载完成了,可以安装了
                } catch (ClientProtocolException e) {  
                    e.printStackTrace();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }.start();  
    }

    通过利用httpClient的get方法,获取指定URL的内容,然后写到本地SD卡中,对于进度条,首先利用m_progressDlg.setMax((int)length);设置进度条的最大值,然后在读取返回结果并写到本地时,利用 m_progressDlg.setProgress(count);设置当前进度。在全部写完以后,调用down()函数,通知HANDER安装程序。
    5、安装程序

    安装程序主要利用下面两个函数:

    /**
     * 告诉HANDER已经下载完成了,可以安装了
     */
    private void down() {
            m_mainHandler.post(new Runnable() {
                public void run() {
                    m_progressDlg.cancel();
                    update();
                }
            });
    }
    /**
     * 安装程序
     */
    void update() {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(new File(Environment
                .getExternalStorageDirectory(), m_appNameStr)),
                "application/vnd.android.package-archive");
        startActivity(intent);
    }

    由于在android程序中必须依循单线程操作UI,所以在非主线程中不能操作UI,否则程序会崩掉,具体参见:《AsnyncTask与handler(一)——AsyncTask异步处理》与《AsnyncTask与handler(二)——handler消息机制》。所以这里作用handler的方式更新UI。

    好了,到这就全部讲完了,下面给出客户端与服务器端源码,懂PHP的童鞋赚到了有木有……

     

    源码地址:http://download.csdn.net/detail/harvic880925/7309013 不要分,仅供分享。

     

     请大家尊重作者原创版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/25191159 不胜感激。

    展开全文
  • 关闭迅雷更新到新版本提示

    千次阅读 2019-01-17 08:36:39
    每次打开迅雷都会自定检查是否是最新版本,如果不是最新版本,迅雷会一直重复弹窗弹出更新到新版本提示: 解决方案 简介:迅雷提示升级是因为每次迅雷主程序启动时都会同时启动一个叫XLLiveUD.exe的程序,这个程序...

    每次打开迅雷都会自动检查是否是最新版本,如果不是最新版本,迅雷会一直重复弹窗弹出更新到新版本的提示:在这里插入图片描述

    解决方案

    简介:迅雷提示升级是因为每次迅雷主程序启动时都会同时启动一个叫XLLiveUD.exe的程序,这个程序会检查更新,所以如果不想让他检查更新,就只需要把他替换掉就可以了(因为如果删除它,每次迅雷启动时都会弹出一个错误对话框,提示找不到文件XLLiveUD.exe


    1. 进入迅雷安装目录,找到XLLiveUD.exe( 可直接在迅雷安装目录中搜索这个文件 ),将其删除。这个就是自动升级的程序,但是删除之后下次开启迅雷会提示该文件丢失。
      在这里插入图片描述
      在这里插入图片描述

    2. 在同一个目录找到迅雷执行程序文件Thunder.exe,这个是就是迅雷桌面快捷方式指到的程序也就是迅雷开启程序。然后复制拷贝Thunder.exe副本,然后将副本文件名更改为迅雷更新执行程序名:XLLiveUD.exe
      在这里插入图片描述
      在这里插入图片描述

    3. 当迅雷程序调用检查更新的执行文件时,实际上相当于重复点击打开迅雷,而迅雷本身不允许重复打开。这样既不会报错也不会造成重复弹屏的问题。从而算是比较完美的解决了关闭迅雷更新到新版本提示的问题(❁´◡`❁)✲゚

    展开全文
  • 微信是我们现在日常生活中使用比较多的常用软件了,几乎每天...今天我们小编刚好遇到一台ipad4平板电脑,客户描述电脑恢复出厂设置以后微信就一直登录不了,登录的时候提示版本过低,需要更新,但是点击去appstore...

    daa297bb6f03790ea6672deb67e696e6.png

    微信是我们现在日常生活中使用比较多的常用软件了,几乎每天我们都会使用到它,大家平时在使用微信的时候有没有发现一个问题,自己的手机或者ipad在恢复出厂设置或者刷机以后微信就用不了了,下载也下载不了,更新也没办法更新的情况?今天我们就来看看怎么解决。

    今天我们小编刚好遇到一台ipad4平板电脑,客户描述电脑恢复出厂设置以后微信就一直登录不了,登录的时候提示版本过低,需要更新,但是点击去appstore里面更新又提示不兼容。

    d5c8f91dd20be2bb9dd1dbce18c9f4f1.png


    版本过低

    更新的时候却又提示无法下载,这样的提示:很显然微信目前已经关闭了老版本微信的登录验证了,只有你安装了最新版本的微信才可以正常登录使用,但是ipad4的话比较老的产品了,最新系统就是10.3.3,很显然已经没有办法安装最新的微信了,难道就没有办法解决了么?

    c933657531f2510620977dd8dd8eba13.png


    无法下载

    经过小编反复研究,终于找到了解决办法,首先将你的ipad进行越狱,一些老版本的ipad设备都是可以直接越狱的,直接下载爱思助手一键越狱,然后打开cydia安装系统文件补丁。

    0d7f76eb740d67eec5d504b5bd03280b.png

    我们越狱成功以后桌面上会生成一个cydia的软件,直接打开,找到软件源,点Cydia/Telesphoreo 点进去

    d7011fe6cdadcb50a9a4aed1705f5920.png

    找到箭头所示的插件,直接点击安装,安装成功以后ipad会注销。

    注销开机以后重新连接电脑,打开爱思助手,如图所示爱思提示已越狱,说明越狱已经成功。

    24b20d400ff6500dc95188c7c4f8960d.png

    这个地方提示已越狱,如果这个地方提示有需要安装的插件,比如提示“安装AFC2” , 那么就需要重新回到刚才安装afc2 的地方,重新安装下,直到上面这个字显示“已越狱”三个字,表示越狱成功。

    之后微信怎么办呢? 打开爱思助手,我的设备,会发现文件管理里,比之前多了很多东西,之前只有一个文件夹“文件系统(用户)”, 然后程序(用户) 里会找到微信。

    84658b0cca8b853925f77a25d7e53799.png

    接下来 打开"微信" 的文件夹,打开 WeChat.app ,找到info.plist配置文件,直接双击打开

    b7a298d8719f9f0a7cae71d6dbf4e722.png

    打开直接编辑

    6dce88857284fe8d7bbaa18afb21be12.png

    将这个版本,原来是7.0.2.24,改成 7.0.13.24, (13是最新版的),这样就保存就可以了。

    然后重新打开微信,直接在ipad 上登录微信, 使用手机号密码登录即可登录成功。 版本会变成最新版7.0.13,然后就可以愉快的使用了。

    bea177a588127d234bb040cc247bc029.png

    这里小编仅仅介绍了苹果ios系统的解决办法,安卓的应该也是一样的原理,但是介已小编没有安卓老设备,无法给大家带来演示,等下次小编有安卓手机的时候再给大家写一个教程。

    更多精彩手机维修资讯请关注昆明九一手机维修中心,如果你在使用手机的过程中遇到什么问题,手机坏了需要维修等问题,可以直接私信或者下面留言给小编,小编看到了会统一回复大家的,小编从事昆明苹果手机维修十余年,欢迎点赞关注

    展开全文
  • 安装了迅雷软件后,如果不是最新版本,迅雷会一直重复弹窗弹出:更新到新版本提示。而迅雷本身又不提供关闭自动更新,或者关闭自动更新提示的功能设置。怎么办?以下以迅雷7.9版本为例进行经验分享   工具/原料...
  • 修改快读使其不提示更新

    千次阅读 2015-05-27 11:16:13
    果断转老版的,可老版每次更新就提示更新,我就想着能不能修改一下,能让它不提示就好啦。 开始百度,如何反编译apk文件,发现了一个的工具。apktool,可以反编译,编译apk文件...
  • 2.embarrassing,浏览器因未更新,打开浏览器右上角时常提示“你的版本太旧”,灰常烦人。 解决方案:右键桌面谷歌浏览器图标,选择属性,在目标地址后添加"--disable-background-networking" 3.提示"Adobe ...
  • //如果有最新版本上传到蒲公英,提示更新 - ( void )hasUpdateVersion{ kWeakSelf( self ); NSDictionary *infoDic=[[ NSBundle mainBundle] infoDictionary]; NSString *currentBulidVersion=infoDic[@ ...
  • 最近有人问我,Github上如何把修改fork到的代码提交到原版本上去,以及如何更新到最新的版本。只针对初学者,大神的话勿喷。 首先说第一个问题。 进入到你修改的某个repository里面(以本人的这个easy-tips为例): ...
  • 1.每次打开xshell或xftp总是会提示更新 2.今天打开xftp的时候,突然提示“要继续使用此程序,您必须应用最新的更新或使用新版本”  吧,程序猿就是专为解决问题而生的! 二.解决方法 1.先修改你电脑时间为前一年....
  • Xshell 6 提示 “要继续使用此程序,您必须应用最新的更新或使用新版本” 解决办法: 使用二进制编辑器修改nslicense.dll文件 文件位置:xshell 安装根目录 具体步骤 步骤1:下载UltraEdit编辑器 步骤2:使用...
  • 于是自己也去下载了4.2,但是下完之后发现eclipse提示ADT版本过低,然后AVD在Eclipse里打不开了,会弹出一个窗口报错。 打开Eclipse报错: 点击AVD 或者 SDK manager报错: 解决方法,到Android S
  • Android中蒲公英第三方提示更新

    千次阅读 2017-03-31 11:02:17
    蒲公英版本提示更新
  • 第一步,显示隐藏文件夹,显示 .svn文件夹     第二步,下载sqllite 下载链接:...第四步,用sqllite,打开wc.db,把uuid修改成服务器的uuid ...错误提示版本库的 UUID“70a379...
  • 打开eclipse后,提示升级,升级之后打开eclipse一样是踢错,很bug,很恶心,错误log如下 This Android SDK requires Android Developer Toolkit version 20.0.0 or above 解决办法很简单,调整SDK配置文件,修改...
  • 1.App版本检测:要实现App的更新下载,我们上面介绍了,前提是服务器要保存一个App的版本号(通常的方式是保存versionCode,当然你要对比versionName也没关系)。当用户去手动检测版本,或者进入首页自动检测时,第...
  • 场景 AndroidStudio中打开新项目提示:This version of the Android Support plugin for IntelliJ IDEA (or Android Studi: ...但是在将Android Studio升级到稳定版的最高版本,检测更新时也检测不
  • 鬼子在式样方面非常执着,如果我告诉他们要在开机时检查一下google_play_services的版本版本较低的情况下还要更新,估计够他们讨论几天,而且八成最后还是打回让我换方案。哎,只能换一个思路了。  实在没有...
  • Android 版本更新

    千次阅读 2019-01-25 21:00:28
    版本更新这一块涉及的知识点比较少,但也花了一天时间,仅做记录用,为了方便大家理解,我画了一张流程图。需求比较简单,以后可以根据产品需求适当更改。 以下版本更新工具类 /** * Created by minmin.shen ...
  • 修改系统的时间是2017年1月,然后进入Xshell6,点击工具—》选项—》更新—》取消实时更新,点击确定就可以了,也就是:你在把时间改成正常的时间,估计就不会出现强制更新了 方法2: 上面的方法我并没有使用过,...
  • 项目中,spring boot版本为:2.2.12.RELEASE,现在更改为指定版本:eg:2.3.7.RELEASE 直接替换build.gradle中的依赖版本号,项目中的依赖包版本号不更改: 进行更改idea配置: file->setting 保存后,idea...
  • xshell5 提示“要继续使用此程序,您必须应用最新的更新或使用新版本” 我的是个人免费版: 使用16进制编辑工具打开安装目录下的文件 nslicense.dll 搜索16进制字符串 7F0C81F98033E1010F8680 修改为 7F0...
  • 简单明了,直接修改系统时间为软件提示之前的时间即可,可以设置到2018年去,但明显不妥,频繁的修改时间 方案二(测试不行): 先修改系统时间为2018年,启动xftp后关闭自动更新,在还原系统时间 工具——》选项...
  • UNITY 打包时提示sdk tools 或 sdk build tools版本低时可以直接点update 按钮进行更新 如题。如果不更新,而选择 : use newest version installed ,打包到结尾时可能会报错,莫名其妙的java错误 而且,SDK...
  • 1.打补丁时,只需将base改为patch 2.需要更改的包必须运行一次,才能上报到bugly。一般这种情况是没有运行打的包
  • iOS开发 版本更新提醒

    千次阅读 2016-08-22 09:35:59
    - (void)versionUpdate{ ... //获得当前发布的版本  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{  //耗时的操作---获取某个应用在AppStore上的信息,更改id就行  NSS
  • Android版本更新知识(检测、升级)总结

    万次阅读 多人点赞 2017-03-14 16:19:39
    Android版本更新知识(检测、升级)总结 本文对Android版本更新的知识做全面的总结,主要包括开发中版本的设置,如何检测本程序的版本版本更新判断和显示,新版本程序的安装。一.版本的基础知识 版本控制的...
  • 第二种方案,我在本地试了,发现我win10,xshell6版本就然不好使,仍然提示更新,估计有些注册信息被放入了C盘,卸载不干净。 第三种方案,没办法了,只有尝试第三种方案。 修改nslicense.dll文件 修改此文件,我...
  • 浅谈android应用的版本更新

    千次阅读 2015-07-15 11:21:50
    我们都知道一个软件不可能一个版本就能做到特别完美,都需要经过不断的修改和优化才能成为一个稳定的版本。我们需要不停的对软件进行 功能添加 ,bug修复以及性能上 的一些优化。所以今天就和大家说一下android app...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 322,059
精华内容 128,823
关键字:

修改版本号还是提示更新