精华内容
下载资源
问答
  • Android版本更新下载提示对话框

    千次阅读 2017-12-18 14:16:12
    Android手机版本更新,使用okhttp网络框架进行网络请求和文件下载操作,使用Handler线程处理progress进度的实时更新,下载之后用户进行选择安装新版本,点击手机返回键或者对话框取消按钮取消文件下载,代码简单易懂...
    Android手机版本更新,使用okhttp网络框架进行网络请求和文件下载操作,使用Handler线程处理progress进度的实时更新,下载之后用户进行选择安装新版本,点击手机返回键或者对话框取消按钮取消文件下载,代码简单易懂,适合初学者,可以直接使用。
    第一次写博客,如有不足之处敬请指教。下面先看效果。
    1.首先,得去清单文件配置好权限。

    <!-- 允许程序接入网络 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />

    2.由于这里使用到了okhttp框架,所以还要去gradle里面加上
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    3.写对话框的布局
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:background="#00000000"
        android:gravity="center"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="30dp"
            android:background="@color/white"
            android:orientation="vertical">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/yellowstroke_radiustop3"
                android:gravity="center"
                android:orientation="horizontal">
    
                <TextView
                    android:id="@+id/notify_title_tv"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:gravity="center_vertical"
                    android:paddingLeft="10dp"
                    android:text="发现新版本"
                    android:textColor="@color/white"
                    android:textSize="16sp" />
    
                <TextView
                    android:id="@+id/update_cancel_tv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:padding="10dp"
                    android:text="取消"
                    android:textColor="@color/white" />
            </LinearLayout>
    
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="提醒"
                android:textColor="@color/colorAccent"
                android:textSize="16sp"
                android:visibility="gone" />
    
            <LinearLayout
                android:id="@+id/progress_linear"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal"
                android:padding="15dp">
    
                <ProgressBar
                    android:id="@+id/progressBar"
                    style="?android:attr/progressBarStyleHorizontal"
                    android:layout_width="fill_parent"
                    android:layout_height="10dp"
                    android:layout_gravity="center_vertical"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="10dp"
                    android:layout_weight="1"
                    android:max="100"
                    android:progress="0"
                    android:progressDrawable="@drawable/download_progress" />
    
                <TextView
                    android:id="@+id/progress_tv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_marginRight="10dp"
                    android:text="下载进度:0%"
                    android:textColor="#333333"
                    android:textSize="12sp" />
            </LinearLayout>
    
        </LinearLayout>
    
    </LinearLayout>

    4.写Activity的相关功能实现的代码
    package com.dyl.downloadprogressdialog;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.Dialog;
    import android.content.Intent;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.Window;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import okhttp3.Call;
    import okhttp3.Callback;
    import okhttp3.Dispatcher;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.Response;
    
    public class MainActivity extends Activity {
        public static final String HTTP_DOWNLOAD_TEST = "http://o1.exmmw.cn/uploads/soft/20160511/xiamiyy.apk";
        public static final String HTTP_BAIDU_URL = "https://www.baidu.com/";
    
        private OkHttpClient client = new OkHttpClient();
        private ProgressBar apkprogressBar;
    
        private TextView mDownloadTv, progress_tv;
        private int fileSize, downLoadFileSize;
        private Dialog versionDialog;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mDownloadTv = findViewById(R.id.download);
            mDownloadTv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    VersionCheck();
                }
            });
        }
    
        private Handler handler = new Handler() {
    
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 0:
                        int p = (int) (((float) msg.arg1 / (float) fileSize) * 100);
                        apkprogressBar.setProgress(p);
                        progress_tv.setText("下载进度:" + p + "%");
                        break;
                    case 1:
                        versionUpdatePop();
                        break;
                }
            }
        };
    
        //版本检查
        private void VersionCheck() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Request request = new Request.Builder().tag("getVersionName").url(HTTP_BAIDU_URL)//请求接口。如果需要传参拼接到接口后面。
                                .build();//创建Request 对象
                        Response response = null;
                        response = client.newCall(request).execute();//得到Response 对象
                        if (response.isSuccessful()) {
                            String myStr = "response.code()=" + response.code() + "\n+response.message()==" + response.body().string();
                            PackageManager packageManager = getPackageManager();
                            PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0);
                            if (!packInfo.versionName.equals(String.valueOf(response.code()))) {
                                Message msg = new Message();
                                msg.what = 1;
                                handler.sendMessage(msg);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        // 版本升级弹出框
        private void versionUpdatePop() {
            versionDialog = new AlertDialog.Builder(MainActivity.this).create();
            versionDialog.show();
            Window window = versionDialog.getWindow();
            window.setContentView(R.layout.dialog_download);
            window.setLayout(android.view.ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    
            apkprogressBar = (ProgressBar) window.findViewById(R.id.progressBar);
            TextView update_cancel_tv = (TextView) window.findViewById(R.id.update_cancel_tv);
            progress_tv = (TextView) window.findViewById(R.id.progress_tv);
    
            update_cancel_tv.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    cancelAll("download");
                    versionDialog.cancel();
                }
            });
    
            downloadFile(HTTP_DOWNLOAD_TEST);
        }
    
        /**
         * 下载文件
         */
        private void downloadFile(String url) {
            Request request = new Request.Builder().url(url).tag("download").build();
            client.newCall(request).enqueue(new Callback() {
    
                @Override
                public void onFailure(Call call, IOException e) {
                    if (e.toString().contains("closed")) {
                        //如果是主动取消的情况下
                        call.cancel();
                    } else {
    
                    }
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (response.isSuccessful()) {
                        try {
                            InputStream is = response.body().byteStream();
                            fileSize = new Long(response.body().contentLength()).intValue();
                            String mDestFileDir = Environment.getExternalStorageDirectory() + "/";
                            String mdestFileName = "Test.apk";
                            File dir = new File(mDestFileDir);
                            if (!dir.exists()) {
                                dir.mkdirs();
                            }
                            File file = new File(dir, mdestFileName);
                            FileOutputStream fos = new FileOutputStream(file);
                            byte[] buf = new byte[1024 * 8];
                            int len = 0;
                            downLoadFileSize = 0;
                            while ((len = is.read(buf)) != -1) {
                                fos.write(buf, 0, len);
                                downLoadFileSize += len;
                                Message msg = new Message();
                                msg.what = 0;
                                msg.arg1 = downLoadFileSize;
                                handler.sendMessage(msg);
                            }
                            fos.flush();
                            update(mDestFileDir + mdestFileName);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    
        // 安装应用
        private void update(String filename) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(new File(filename)), "application/vnd.android.package-archive");// app.getVersionName()
            startActivity(intent);
        }
    
        //取消指定标签的的网络请求
        private void cancelAll(Object tag) {
            Dispatcher dispatcher = client.dispatcher();
            if (tag != null) {
                synchronized (dispatcher) {
                    for (Call call : dispatcher.queuedCalls()) {
                        if (tag.equals(call.request().tag())) {
                            call.cancel();
                        }
                    }
                    for (Call call : dispatcher.runningCalls()) {
                        if (tag.equals(call.request().tag())) {
                            call.cancel();
                        }
                    }
                }
            } else {
                dispatcher.cancelAll();
            }
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            //点击返回键去掉版本升级
            if (versionDialog != null && versionDialog.isShowing()) {
                cancelAll("download");
                versionDialog.cancel();
            }
            return super.onKeyDown(keyCode, event);
        }
    }
    

    代码就是这么简单,如果还是不清楚可以下载下面的源码文件直接使用,如有疑问,欢迎提出。
    或者在这里下载:点击打开链接
    
    展开全文
  • 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 不胜感激。

    展开全文
  • //0提示更新 ; 1强制更新 mDesc = versionInfoBean.getData().getMessage(); mVersionName = versionInfoBean.getData().getCodeX(); if (builder == null) { dialogForUpdate(mVersionName, mDesc, appName, ...
    
    
     public static String UPDATE_PROVIDER = "com.xxx.xxx.provider";//包名+provider
        private String mDesc;
        private int isNeedUpdate;
        private String packUrl;
        private MDialog progressBardialog;
        private String appName;
        private String mVersionName;
        private ProgressBar progressBar;
        private TextView mtvNumber;
        MDialog.Builder builder;
        private MDialog mDialog;
     private void checkVersion() {
            HashMap<String, String> map = new HashMap<>();
            map.put(Constant.VERSION, AppUtil.getApplicaionVersionName(mContext));//
            map.put("deviceType", "0");//手机类型(0、android 1、iphone)
            PackOkHttpUtils.postHttp(this, HttpBaseBean.class, ApiConfig.SYS_VERSION_INFO, false,
                    map, new PackOkHttpUtils.HttpCallBackListener<HttpBaseBean>() {
                        @Override
                        public void onSuccess(HttpBaseBean baseBean, String response) {
                            if (baseBean.getCode() == Constant.HTTP_SUCCESS) {
                                VersionInfoBean versionInfoBean = JsonUtils.fromJson(response,
                                        VersionInfoBean.class);
                                if (versionInfoBean.getData() != null && !MStringUtils.isNullOrEmpty
                                        (versionInfoBean.getData().getUrl()) && !MStringUtils.isNullOrEmpty(versionInfoBean.getData().getCodeX())) {
    
                                    String newVersion = versionInfoBean.getData().getCodeX();
                                    int newVcode = Integer.parseInt(newVersion);
                                    int oldVcode = AppUtil.getVersionCode(mContext);
                                    if (newVcode > oldVcode) {
                                        appName = versionInfoBean.getData().getName();
                                        packUrl = versionInfoBean.getData().getUrl();
                                        isNeedUpdate = versionInfoBean.getData().getMust();//0提示更新  ; 1强制更新
                                        mDesc = versionInfoBean.getData().getMessage();
                                        mVersionName = versionInfoBean.getData().getCodeX();
                                        if (builder == null) {
                                            dialogForUpdate(mVersionName, mDesc, appName, packUrl);
                                        }
                                        if (!SPUtils.getString("Later").equals("Later")) {
                                            handler.sendEmptyMessageDelayed(99, 1000);
                                        }
                                    }
                                } 
                            }
                        }
    
                        @Override
                        public void onError(String response) {
    
                        }
                    });
    
        }

        @Override
        protected void onStart() {
            super.onStart();
            checkVersion();//检查更新我放在onstart方法里面是方便用户在每次回到这个界面的时候都能检测到更新
        }

    private void dialogForUpdate(String versionName, String desc, final String appName,
                                     final String packUrl) {
    
            builder = new MDialog.Builder(this, "检测到最新版本:" + versionName, desc);
            builder.isConLeft(true);
            builder.setPositiveButton("立即更新", new DialogInterface.OnClickListener() {
    
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (isNeedUpdate == 1) {
                        PermissionGen.with(MainActivity.this)
                                .addRequestCode(50)
                                .permissions(
                                        Manifest.permission.READ_EXTERNAL_STORAGE,
                                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                                ).request();
                        getLatestVersion();
                    } else if (isNeedUpdate == 0) {
                        //启动服务
                        Intent intent = new Intent(MainActivity.this, DownloadService.class);
                        intent.putExtra("appName", appName);
                        intent.putExtra("url", packUrl);
                        startService(intent);
                    }
                }
            });
            builder.setNegativeButton("稍后再说", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    SPUtils.putString("Later", "Later");
                    dialog.dismiss();
    
                }
            });
            if (isNeedUpdate == 1) {
                builder.isNega(false);
                builder.setCancelable(false);
            } else {
                builder.isNega(true);
                builder.setCancelable(true);
            }
            mDialog = builder.create();
        }

    private Handler handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                switch (msg.what) {
                    case 99:
                        if (AppUtil.isForeground(mContext, getComponentName()
                                .getClassName())) {
                            if (!mDialog.isShowing()) {
                                mDialog.show();
                            }
                        }
                        break;
                }
                return false;
            }
        });

     private void getLatestVersion() {
            if (packUrl != null) {
                progressBardialog.setCancelable(true);
                progressBardialog.setCanceledOnTouchOutside(false);
                progressBar.setMax(100);
                progressBardialog.show();
                progressBardialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
                    @Override
                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent
                                .ACTION_DOWN) {
                            setAdvToast();
                            dismiss();
                        }
                        return false;
                    }
                });
                downLoad();
            }
        }
    
        private void downLoad() {
            if (MStringUtils.isNullOrEmpty(appName)) {
                appName = "yudaosz.apk";
            }
            OkHttpUtils.get()
                    .url(packUrl)
                    .headers(PackOkHttpUtils.getHeadsMap(this))
                    .tag(MainActivity.class)
                    .addParams("version", AppUtil.getApplicaionVersionName(getApplicationContext()))
                    .build()
                    .execute(new FileCallBack(Environment.getExternalStoragePublicDirectory
                            (Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), appName) {
                        @Override
                        public void inProgress(float progress, long total, int id) {
                            super.inProgress(progress, total, id);
                            int progressInt = (int) (progress * 100);
                            progressBar.setProgress(progressInt);
                            mtvNumber.setText(progressInt + "%");
                        }
    
                        @Override
                        public void onError(Call call, Exception e, int id) {
                            MyToast.showMessage("下载失败");
                        }
    
                        @Override
                        public void onResponse(File response, int id) {
    
                            try {
                                SPUtils.putBoolean("VersionUpdate", false);
                                String authority = UPDATE_PROVIDER;
                                Uri fileUri = FileProvider.getUriForFile(getApplicationContext(),
                                        authority, response);
                                Intent intent = new Intent(Intent.ACTION_VIEW);
                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                //7.0以上需要添加临时读取权限
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                    intent.setDataAndType(fileUri, "application/vnd.android" +
                                            ".package-archive");
                                } else {
                                    Uri uri = Uri.fromFile(response);
                                    intent.setDataAndType(uri, "application/vnd.android" +
                                            ".package-archive");
                                }
    
                                startActivity(intent);
                                //弹出安装窗口把原程序关闭。
                                //避免安装完毕点击打开时没反应
                                killProcess(android.os.Process.myPid());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
    
    
        }
    
        private void dismiss() {
            if (isFinishing()) {
                return;
            }
            if (null != progressBardialog && progressBardialog.isShowing()) {
                progressBardialog.dismiss();
                OkHttpUtils.getInstance().cancelTag(MainActivity.class);
                MyToast.showMessage("取消更新");
            }
        }
    
    
        private void progressBarDialog() {
            progressBardialog = new MDialog(mContext, R.style.Dialog);
            View layoutUpdate = LayoutInflater.from(mContext).inflate(R.layout.dialog_update_layout,
                    null);
            progressBardialog.addContentView(layoutUpdate, new ViewGroup.LayoutParams(ViewGroup
                    .LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            progressBardialog.setCancelable(false);
            progressBar = (ProgressBar) layoutUpdate.findViewById(R.id.mpb_update);
            progressBardialog.setContentView(layoutUpdate);
            mtvNumber = (TextView) layoutUpdate.findViewById(R.id.mtv_number);
        }
    

    public class DownloadService extends Service {//下载服务
    
        //定义notify的id,避免与其它的notification的处理冲突
        private static final int NOTIFY_ID = 0;
    
        private NotificationManager mNotificationManager;
        private NotificationCompat.Builder mBuilder;
    
        //定义个更新速率,避免更新通知栏过于频繁导致卡顿
        private float rate = .0f;
        private String url;
        private String appName;
        private String target;
    //    private TextView mtvNumber;
    //    private MDialog progressBardialog;
    //    private ProgressBar progressBar;
    
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            MLog.e("fuwu", "laile");
            return null;
        }
    
        @Override
        public void unbindService(ServiceConnection conn) {
            super.unbindService(conn);
            mNotificationManager.cancelAll();
            mNotificationManager = null;
            mBuilder = null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            appName = intent.getStringExtra("appName");
    
            if (MStringUtils.isNullOrEmpty(appName)) {
                appName = "xysz.apk";
            }
    
            url = intent.getStringExtra("url");
            //创建下载APK的路径
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
            }
    
    
            setNotification();
            // 通过通知管理器发送通知֪
            if (url != null) {
                downApk(url);
            }
            handler.sendEmptyMessage(0);
            return super.onStartCommand(intent, flags, startId);
        }
    
    
        /**
         * 创建通知栏
         */
        private void setNotification() {
            if (MStringUtils.isNullOrEmpty(url)) {
                complete("下载路径错误");
                return;
            }
            if (mNotificationManager == null)
                mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            mBuilder = new NotificationCompat.Builder(this);
    
            mBuilder.setContentTitle("开始下载")
                    .setAutoCancel(true)//打开程序后图标消失
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentText("正在下载:")
                    .setTicker("CraveHome开始下载")
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                    .setOngoing(true)
                    .setAutoCancel(true)
                    .setWhen(System.currentTimeMillis());
            mNotificationManager.notify(NOTIFY_ID, mBuilder.build());
        }
    
        /**
         * 下载完成
         */
        private void complete(String msg) {
            if (mBuilder != null) {
                mBuilder.setContentTitle("新版本").setContentText(msg);
                Notification notification = mBuilder.build();
                notification.flags = Notification.FLAG_AUTO_CANCEL;
                mNotificationManager.notify(NOTIFY_ID, notification);
            }
            stopSelf();
        }
    
    
        /**
         * 开始下载apk
         */
        public void downApk(String url) {
    
            OkHttpUtils.get()
                    .url(url)
                    .headers(PackOkHttpUtils.getHeadsMap(this))
                    .tag(this)
                    .addParams(Constant.VERSION, AppUtil.getApplicationVersionName()) TODO: 2018/5/25
                    .build()
                    .execute(new FileCallBack(target, appName) {
                        @Override
                        public void inProgress(float progress, long total, int id) {
                            super.inProgress(progress, total, id);
                            int progressInt = (int) (progress * 100);
                            Message message = Message.obtain();
                            message.what = 2;
                            message.obj = progressInt;
                            handler.sendMessage(message);
                        }
    
                        @Override
                        public void onError(Call call, Exception e, int id) {
                            Message message = Message.obtain();
                            message.what = 1;
                            message.obj = "下载错误";
                            handler.sendMessage(message);
                        }
    
                        @Override
                        public void onResponse(File response, int id) {
                            try {
                                SPUtils.putBoolean("VersionUpdate", false);
                                String authority = UPDATE_PROVIDER;
                                Uri fileUri = FileProvider.getUriForFile(getApplicationContext(), authority, response);
                                Intent intent = new Intent(Intent.ACTION_VIEW);
                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
                                //7.0以上需要添加临时读取权限
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                    intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
                                } else {
                                    Uri uri = Uri.fromFile(response);
                                    intent.setDataAndType(uri, "application/vnd.android.package-archive");
                                }
    
                                startActivity(intent);
                                stopSelf();
                                //弹出安装窗口把原程序关闭。
                                //避免安装完毕点击打开时没反应
                                killProcess(android.os.Process.myPid());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
    
                        }
                    });
        }
    
    
        /**
         * 路径为根目录
         * 创建文件名称为 updateDemo.apk
         */
        private File createFile() {
            String root = Environment.getExternalStorageDirectory().getPath();
            File file = new File(root, "yudaosz.apk");
            if (file.exists())
                file.delete();
            try {
                file.createNewFile();
                return file;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 把处理结果放回ui线程
         */
        private Handler handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                switch (msg.what) {
                    case 0:
                        MyToast.showMessage("下载开始");
    //                    progressBarDialog();
                        break;
    
                    case 1:
                        mNotificationManager.cancel(NOTIFY_ID);
                        MyToast.showMessage((String) msg.obj);
                        stopSelf();
                        break;
    
                    case 2: {
                        int progress = (int) msg.obj;
                        mBuilder.setContentTitle("正在下载:新版本...")
                                .setContentText(String.format(Locale.CHINESE, "%d%%", progress))
                                .setProgress(100, progress, false)
                                .setWhen(System.currentTimeMillis());
    //                    progressBar.setProgress(progress);
                        Notification notification = mBuilder.build();
                        notification.flags = Notification.FLAG_AUTO_CANCEL;
                        mNotificationManager.notify(NOTIFY_ID, notification);
                    }
                    break;
    
                }
                return false;
            }
        });
    
    
        /**
         * 是否运行在用户前面
         */
        private boolean onFront() {
            ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
            if (appProcesses == null || appProcesses.isEmpty())
                return false;
    
            for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
                if (appProcess.processName.equals(getPackageName()) &&
                        appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * 销毁时清空一下对notify对象的持有
         */
        @Override
        public void onDestroy() {
            mNotificationManager = null;
            super.onDestroy();
        }
    
    
    }
      <!-- manifest注册更新服务 -->
            <service android:name=".service.DownloadService"/>
     <!-- 适配7.0系统数据   android:authorities= "包名.provider" -->
            <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.xxx.xxx.provider"  
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/provider_paths"/>
            </provider>

    下面是provider_paths的内容

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <paths>
            <external-path name="download"  path=""/>
        </paths>
    </resources>



    //Splash界面 “提示更新”的默认值,默认为空
            SPUtils.putString("Later", "");






    展开全文
  • 2、更新提示

    千次阅读 2013-12-23 19:25:16
    在进入splash界面的时候后台启动线程,联网检查是否有更新版本可用,如果没有新版本则splash界面显示后进入主界面,否则显示升级对话框让用户选择是否进行更新。 1、权限设置 因为需要联网,所以AndroidManifest.xml...

    在进入splash界面的时候后台启动线程,联网检查是否有更新版本可用,如果没有新版本则splash界面显示后进入主界面,否则显示升级对话框让用户选择是否进行更新。

    1、权限设置

    因为需要联网,所以AndroidManifest.xml文件需要添加访问网络的权限:

    <uses-permission android:name="android.permission.INTERNET" />
    本人就是由于忘记添加该权限,在后面的运行中出现错误:

    12-23 03:24:26.999    1528-1541/com.example.mobilesafe W/System.err﹕ java.net.SocketException: socket failed: EACCES (Permission denied)
    12-23 03:24:26.999    1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.socket(IoBridge.java:576)
    12-23 03:24:27.009    1528-1541/com.example.mobilesafe W/System.err﹕ at java.net.PlainSocketImpl.create(PlainSocketImpl.java:201)
    12-23 03:24:27.009    1528-1541/com.example.mobilesafe W/System.err﹕ at java.net.Socket.checkOpenAndCreate(Socket.java:664)
    12-23 03:24:27.009    1528-1541/com.example.mobilesafe W/System.err﹕ at java.net.Socket.connect(Socket.java:808)
    12-23 03:24:27.009    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)
    12-23 03:24:27.009    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.Connection.connect(Connection.java:101)
    12-23 03:24:27.009    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
    12-23 03:24:27.019    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
    12-23 03:24:27.019    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
    12-23 03:24:27.029    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
    12-23 03:24:27.029    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
    12-23 03:24:27.029    1528-1541/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
    12-23 03:24:27.029    1528-1541/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.SplashActivity$checkUpdate.run(SplashActivity.java:146)
    12-23 03:24:27.029    1528-1541/com.example.mobilesafe W/System.err﹕ at java.lang.Thread.run(Thread.java:841)
    12-23 03:24:27.029    1528-1541/com.example.mobilesafe W/System.err﹕ Caused by: libcore.io.ErrnoException: socket failed: EACCES (Permission denied)
    12-23 03:24:27.079    1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.Posix.socket(Native Method)
    12-23 03:24:27.079    1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:181)
    12-23 03:24:27.079    1528-1541/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.socket(IoBridge.java:561)
    12-23 03:24:27.079    1528-1541/com.example.mobilesafe W/System.err﹕ ... 13 more

    2、服务器更新配置

    这里使用wampserver搭建本地服务器,更新配置文件放在X:\wamp\www\app\mobilesafe目录下,配置内容为:

    <?xml version="1.0" encoding="utf-8"?>
    <info>
        <ver>2.0</ver>
        <desc>亲,有新版本了,赶紧更新吧!</desc>
        <apkurl>http://10.0.2.2/app/mobilesafe/mobilesafe.apk</apkurl>
     </info>


    3、设置服务器地址

    因为服务器地址属于常量字符串,这里添加到strings.xml中:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">mobilesafe</string>
        <string name="serverurl">http://10.0.2.2/app/mobilesafe/update.xml</string>
    </resources>
    

    这里是使用本机进行测试的,注意Android访问本机的IP地址是:10.0.2.2,如果使用127.0.0.1会出现如下错误:

    12-23 03:29:15.189    1573-1586/com.example.mobilesafe W/System.err﹕ java.net.ConnectException: failed to connect to /127.0.0.1 (port 80) after 5000ms: isConnected failed: ECONNREFUSED (Connection refused)
    12-23 03:29:15.189    1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.isConnected(IoBridge.java:223)
    12-23 03:29:15.189    1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.connectErrno(IoBridge.java:161)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.connect(IoBridge.java:112)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at java.net.Socket.connect(Socket.java:843)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.Platform.connectSocket(Platform.java:131)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.Connection.connect(Connection.java:101)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.SplashActivity$checkUpdate.run(SplashActivity.java:146)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at java.lang.Thread.run(Thread.java:841)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ Caused by: libcore.io.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ at libcore.io.IoBridge.isConnected(IoBridge.java:208)
    12-23 03:29:15.199    1573-1586/com.example.mobilesafe W/System.err﹕ ... 15 more

    相关参考: http://www.myexception.cn/operating-system/754403.html


    4、更新信息结构体

    按照服务器更新配置,更新信息共有三个字段:版本号,更新提示文本,apk下载地址:

    package com.example.mobilesafe;
    
    /**
     * Created by sing on 13-12-23.
     */
    public class UpdateInfo {
        //服务器端版本号
        private String version;
    
        //服务器端升级提示
        private String desc;
    
        //服务器端apk下载地址
        private String apkurl;
    
        public String getVersion() {
            return version;
        }
    
        public void setVersion(String version) {
            this.version = version;
        }
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    
        public String getApkurl() {
            return apkurl;
        }
    
        public void setApkurl(String apkurl) {
            this.apkurl = apkurl;
        }
    
    }
    

    5、XML更新配置解析类

    注意XmlPullParser解析XML的nextText存在bug:

    12-23 03:46:07.439    1729-1748/com.example.mobilesafe W/System.err﹕ org.xmlpull.v1.XmlPullParserException: END_TAG expected (position:START_TAG <version>@3:14 in java.io.InputStreamReader@b2ef2718)
    12-23 03:46:07.449    1729-1748/com.example.mobilesafe W/System.err﹕ at org.kxml2.io.KXmlParser.nextText(KXmlParser.java:2077)
    12-23 03:46:07.479    1729-1748/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.UpdateInfoParser.getUpdateInfo(UpdateInfoParser.java:33)
    12-23 03:46:07.479    1729-1748/com.example.mobilesafe W/System.err﹕ at com.example.mobilesafe.SplashActivity$checkUpdate.run(SplashActivity.java:153)
    12-23 03:46:07.499    1729-1748/com.example.mobilesafe W/System.err﹕ at java.lang.Thread.run(Thread.java:841)
    

    参考解决:http://blog.csdn.net/nxh_love/article/details/7109762,

    这里使用的方法是:当前的位置不是END_TAG时,在调用nextText()之后再调用nextTag(),完整代码:

    package com.example.mobilesafe;
    
    import android.util.Xml;
    import org.xmlpull.v1.XmlPullParser;
    import org.xmlpull.v1.XmlPullParserException;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * Created by sing on 13-12-23.
     */
    
    public class UpdateInfoParser {
        /**
         *解析一个utf-8格式的xml输入流,返回一个UpdateInfo对象
         * XmlPullParser解析bug参考解决:http://blog.csdn.net/nxh_love/article/details/7109762
         * @param is
         * @return UpdateInfo对象
         * @throws XmlPullParserException
         * @throws IOException
         */
        public static UpdateInfo getUpdateInfo(InputStream is) throws XmlPullParserException, IOException {
            UpdateInfo info = new UpdateInfo();
    
            //获取一个pull解析的实例
            XmlPullParser parser = Xml.newPullParser();
    
            //解析xml
            parser.setInput(is, "UTF-8");
            parser.nextTag();
            int type = parser.getEventType();
            while (parser.nextTag() == XmlPullParser.START_TAG) {
                String tag = parser.getName();
                String text = parser.nextText();
                if (parser.getEventType() != XmlPullParser.END_TAG) {
                    parser.nextTag();
                }
                if (tag.equals("ver")) {
                    info.setVersion(text);
                } else if (tag.equals("desc")) {
                    info.setDesc(text);
                } else if (tag.equals("apkurl")) {
                    info.setApkurl(text);
                }
            }
    
            return info;
        }
    }
    

    6、SplashActivity::OnCreate创建检查更新的线程

            //检查更新
            new Thread(new checkUpdate()) {
            }.start();


        /**
         * 检查更新
         */
        private class checkUpdate implements Runnable {
           public void run() {
               long startTime = System.currentTimeMillis();
               long endTime = startTime;
               Message msg = Message.obtain();
               try {
                   //获取服务器更新地址
                   String serverurl = getResources().getString(R.string.serverurl);
                   URL url = new URL(serverurl);
                   HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                   conn.setRequestMethod("GET");
                   conn.setConnectTimeout(5000);
                   int code = conn.getResponseCode();
                   if (code == 200) {
                       //success
                       InputStream is = conn.getInputStream();
                        //解析出更新信息
                       updateinfo = UpdateInfoParser.getUpdateInfo(is);
                       endTime = System.currentTimeMillis();
                       long time = endTime - startTime;
                       if (time < 2000) {
                           try {
                               Thread.sleep(2000 - time);
                           } catch (InterruptedException e) {
                               e.printStackTrace();
                           }
                       }
    
                       msg.what = GET_INFO_SUCCESS;
                       handler.sendMessage(msg);
                   } else {
                       //服务器错误
                       msg.what = SERVER_ERROR;
                       handler.sendMessage(msg);
                       endTime = System.currentTimeMillis();
                       long time = endTime - startTime;
                       if (time < 2000) {
                           try {
                               Thread.sleep(2000 - time);
                           } catch (InterruptedException e) {
                               e.printStackTrace();
                           }
                       }
                   }
    
               } catch (MalformedURLException e) {
                   msg.what = SERVER_URL_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (ProtocolException e) {
                   msg.what = PROTOCOL_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (IOException e) {
                   msg.what = IO_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (XmlPullParserException e) {
                   msg.what = XML_PARSER_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (Exception e) {
                   msg.what = UNKNOWN_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               }
    
           }
        }


    7、添加消息处理函数,在界面中统一显示

       /**
         * 消息处理器
         */
        private Handler handler = new Handler() {
             public void handleMessage(Message msg) {
                switch (msg.what) {
                    case GET_INFO_SUCCESS:
                        String serverVersion = updateinfo.getVersion();
                        String currentVersion = getVersion();
                        if (currentVersion.equals(serverVersion)) {
                            Log.i(TAG, "版本号相同无需升级,直接进入主界面");
                        }else {
                            Log.i(TAG, "版本号不同需升级,显示升级对话框");
                            showUpdateDialog();
                        }
                        break;
                    case SERVER_ERROR:
                        Toast.makeText(getApplicationContext(), "服务器内部异常", 1).show();
                        break;
                    case SERVER_URL_ERROR:
                        Toast.makeText(getApplicationContext(), "服务器路径错误", 1).show();
                        break;
                    case PROTOCOL_ERROR:
                        Toast.makeText(getApplicationContext(), "协议错误", 1).show();
                        break;
                    case XML_PARSER_ERROR:
                        Toast.makeText(getApplicationContext(), "XML解析错误", 1).show();
                        break;
                    case IO_ERROR:
                        Toast.makeText(getApplicationContext(), "I/O错误", 1).show();
                        break;
                    case UNKNOWN_ERROR:
                        Toast.makeText(getApplicationContext(), "未知错误", 1).show();
                        break;
                }
            }
        };

    8、当本地版本号与服务器端获取的版本号不同时提示升级对话框

    /**
         * 显示升级提示对话框
         */
        protected void showUpdateDialog() {
            //创建对话框构造器
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            //设置对话框图标
            builder.setIcon(getResources().getDrawable(R.drawable.notification));
            //设置对话框标题
            builder.setTitle("升级提示");
            //设置更新信息为对话框提示内容
            builder.setMessage(updateinfo.getDesc());
            //设置升级按钮及响应事件
            builder.setPositiveButton("升级", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
    
                }
            });
            //设置取消按钮及响应事件
            builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
    
                }
            });
    
            //创建并显示对话框
            builder.create().show();
        }

    9、SplashActivity完整代码

    package com.example.mobilesafe;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.os.Message;
    import android.util.Log;
    import android.view.Window;
    import android.view.WindowManager;
    import android.view.animation.AlphaAnimation;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    import android.widget.Toast;
    import org.xmlpull.v1.XmlPullParserException;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.ProtocolException;
    import java.net.URL;
    import android.os.Handler;
    
    public class SplashActivity extends Activity {
        //常量定义
        public static final int UNKNOWN_ERROR = 99;
        public static final int GET_INFO_SUCCESS = 100;
        public static final int SERVER_ERROR = 101;
        public static final int SERVER_URL_ERROR = 102;
        public static final int PROTOCOL_ERROR = 103;
        public static final int IO_ERROR = 104;
        public static final int XML_PARSER_ERROR = 105;
        public static final String TAG = "SplashActivity";
    
        //获取的服务器端的更新信息
        UpdateInfo updateinfo;
    
        //显示版本号的tv控件
        private TextView tv_splash_version;
    
        //布局控件
        private RelativeLayout r1_splash;
    
        /**
         * Called when the activity is first created.
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            //设置无标题栏
            requestWindowFeature(Window.FEATURE_NO_TITLE);
    
            //设置全屏模式
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
            //设置局部,显示版本号
            setContentView(R.layout.activity_splash);
            r1_splash = (RelativeLayout)findViewById(R.id.r1_splash);
            tv_splash_version = (TextView)findViewById(R.id.tv_splash_version);
            tv_splash_version.setText("版本号:" + getVersion());
    
            //显示渐进动画
            AlphaAnimation aa = new AlphaAnimation(0.3f, 1.0f);
            aa.setDuration(2000);
            r1_splash.startAnimation(aa);
    
            //检查更新
            new Thread(new checkUpdate()) {
            }.start();
        }
    
        //获取当前应用程序的版本号
        private String getVersion() {
            String version = "";
    
            //获取系统包管理器
            PackageManager pm = this.getPackageManager();
            try {
                PackageInfo info = pm.getPackageInfo(getPackageName(), 0);
                version = info.versionName;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return version;
        }
    
        /**
         * 消息处理器
         */
        private Handler handler = new Handler() {
             public void handleMessage(Message msg) {
                switch (msg.what) {
                    case GET_INFO_SUCCESS:
                        String serverVersion = updateinfo.getVersion();
                        String currentVersion = getVersion();
                        if (currentVersion.equals(serverVersion)) {
                            Log.i(TAG, "版本号相同无需升级,直接进入主界面");
                        }else {
                            Log.i(TAG, "版本号不同需升级,显示升级对话框");
                            showUpdateDialog();
                        }
                        break;
                    case SERVER_ERROR:
                        Toast.makeText(getApplicationContext(), "服务器内部异常", 1).show();
                        break;
                    case SERVER_URL_ERROR:
                        Toast.makeText(getApplicationContext(), "服务器路径错误", 1).show();
                        break;
                    case PROTOCOL_ERROR:
                        Toast.makeText(getApplicationContext(), "协议错误", 1).show();
                        break;
                    case XML_PARSER_ERROR:
                        Toast.makeText(getApplicationContext(), "XML解析错误", 1).show();
                        break;
                    case IO_ERROR:
                        Toast.makeText(getApplicationContext(), "I/O错误", 1).show();
                        break;
                    case UNKNOWN_ERROR:
                        Toast.makeText(getApplicationContext(), "未知错误", 1).show();
                        break;
                }
            }
        };
    
        /**
         * 检查更新
         */
        private class checkUpdate implements Runnable {
           public void run() {
               long startTime = System.currentTimeMillis();
               long endTime = startTime;
               Message msg = Message.obtain();
               try {
                   //获取服务器更新地址
                   String serverurl = getResources().getString(R.string.serverurl);
                   URL url = new URL(serverurl);
                   HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                   conn.setRequestMethod("GET");
                   conn.setConnectTimeout(5000);
                   int code = conn.getResponseCode();
                   if (code == 200) {
                       //success
                       InputStream is = conn.getInputStream();
                        //解析出更新信息
                       updateinfo = UpdateInfoParser.getUpdateInfo(is);
                       endTime = System.currentTimeMillis();
                       long time = endTime - startTime;
                       if (time < 2000) {
                           try {
                               Thread.sleep(2000 - time);
                           } catch (InterruptedException e) {
                               e.printStackTrace();
                           }
                       }
    
                       msg.what = GET_INFO_SUCCESS;
                       handler.sendMessage(msg);
                   } else {
                       //服务器错误
                       msg.what = SERVER_ERROR;
                       handler.sendMessage(msg);
                       endTime = System.currentTimeMillis();
                       long time = endTime - startTime;
                       if (time < 2000) {
                           try {
                               Thread.sleep(2000 - time);
                           } catch (InterruptedException e) {
                               e.printStackTrace();
                           }
                       }
                   }
    
               } catch (MalformedURLException e) {
                   msg.what = SERVER_URL_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (ProtocolException e) {
                   msg.what = PROTOCOL_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (IOException e) {
                   msg.what = IO_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (XmlPullParserException e) {
                   msg.what = XML_PARSER_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               } catch (Exception e) {
                   msg.what = UNKNOWN_ERROR;
                   handler.sendMessage(msg);
                   e.printStackTrace();
               }
    
           }
        }
    
        /**
         * 显示升级提示对话框
         */
        protected void showUpdateDialog() {
            //创建对话框构造器
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            //设置对话框图标
            builder.setIcon(getResources().getDrawable(R.drawable.notification));
            //设置对话框标题
            builder.setTitle("升级提示");
            //设置更新信息为对话框提示内容
            builder.setMessage(updateinfo.getDesc());
            //设置升级按钮及响应事件
            builder.setPositiveButton("升级", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
    
                }
            });
            //设置取消按钮及响应事件
            builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
    
                }
            });
    
            //创建并显示对话框
            builder.create().show();
        }
    }
    

    10、运行效果图

    本地版本号与服务器版本号相同时直接进入主界面:

    12-23 05:43:33.279    2125-2125/com.example.mobilesafe I/SplashActivity﹕ 版本号相同无需升级,直接进入主界面

    本地版本号与服务器版本号不同时显示提示升级对话框:

    12-23 05:44:37.349    2125-2125/com.example.mobilesafe I/SplashActivity﹕ 版本号不同需升级,显示升级对话框







    展开全文
  • 下载apk以及提示对话框的实现 一、步骤: ...1. 提示用户更新的时候,实现必须更新的方法如下:显示的对话框只显示更新按钮,也就是只能选择更新。 2. 下载的时候,下载对话框的页面显示一个进度条来显示下
  • 刚才用 Ubuntu 16.04更新软件时提示“需要安装不能信任的软件包”,“这个动作需要从没有授权的软件源来安装软件包”, 赋予权限执行仍然无法安装,上网查了一下,只需要升级一下软件源列表(在终端下执行 sudo apt-...
  • Android 提示版本更新的实现

    千次阅读 2012-06-21 15:26:43
    应用软件更新一般步骤: 1、首先检测网络是否存在,如果存在进行版本信息检测 NetworkInfo networkInfo = NetInfo.getNetworkInfo(getActivity()); if (networkInfo != null) { state = networkInfo....
  • GridView更新和删除显示提示信息

    千次阅读 2006-02-24 21:08:00
    以前做Asp.Net 1.X是经常会碰到处理列表控件的提示情况,现在开始学习Asp.Net2.0了, 用GridView完成相似的事情,更新和删除显示提示信息,确认后使用SqlDataSource 完成数据库操作的 void GridView1_RowCommand...
  • 给大家介绍个东西,MarkDown真的超级超级好用。哈哈。好了,正题内容如下:先说明,此文章是教程详解,而不是直接拿来用的Demo,想要Demo的朋友可以在下面留言或者私信,看到有要的...先看一下效果: 1,检测更新 /*
  • android应用的版本更新,以及推送提示用户最新版本下载代码与逻辑: 作为一名Android软件开发的程序员,这个功能是必须要掌握的,因为这个功能不管你是什么app都会用到,除非你这个项目废弃了,因为在我的微信...
  • //如果当前手机安装app的bulid号<蒲公英上最新打包的bulid号,则提示更新 UIAlertController *ac = [UIAlertController alertControllerWithTitle:@ "版本有更新" message:@ "检测到新版本,是否更新?" ...
  • iOS App版本更新

    千次阅读 2016-09-26 15:50:55
    可选更新:弹框时有取消更新两个按钮,用户可以选择取消按钮(增加新的功能,改善用户的体验等,这种更新不会影响软件的正常的使用) 强制更新:弹框时只有一个更新按钮,用户没得选择,必须更新(系统重大漏洞,...
  • Android版本检测更新升级

    千次阅读 2016-12-05 16:04:11
    一般的话,我们的apk里面新增加了内容,客户端会提示用户进行更新,那么我们就需要获取本地的apk的版本号和服务端的版本进行比较,获取服务端的版本号就是一个网络请求,这里就不说了,如果服务端的版本号大于...
  • Qt 之 自定义提示信息框—QQ风格

    万次阅读 2016-12-20 12:42:46
    一、简述在 Qt 之 自定义提示信息框—迅雷风格 这篇文章中讲述了如何实现迅雷风格的自定义提示框。那么在这一篇中我们就讲述一下如何实现QQ风格的提示框。整体代码与Qt 之 自定义提示信息框—迅雷风格 中的代码类似...
  • 6.登记前Apple ID 的双重认证(Two-factor authentication for Apple ID) 点击说明中的链接进入双重认证页面 英文地址:https://support.apple.com/en-us/HT204915 Two-factor authentication for Apple ID ...
  • Android检查更新下载安装

    万次阅读 多人点赞 2017-09-05 15:32:00
    检查更新是任何app都会用到功能,任何一个app都不可能第一个版本就能把所有的需求都能实现,通过不断的挖掘需求迭代才能使app变的越来越好。检查更新自动下载安装分以下几个步骤: 请求服务器判断是否有最新版本...
  • Android更新带进度条的通知栏

    万次阅读 多人点赞 2015-08-06 15:47:05
    在网上查询了下,Android版本更新通知栏带进度条,醉了,基本都是复制过来,有的代码不全,连源码下载都没有,有下载也需要积分,还不能用,真黑心啊!!之前自己也写过自定义通知栏Notification,想了还是自己写吧...
  • 这期看下去你会发现很硬核,而且我会持续更新,啥也不说了,看在我熬夜一个月满脸痘痘的份上,你可以点赞了哈哈。 注:如果图被压缩了,可以去公众号【三太子敖丙】回复【复习】获取原图 Spring Spring框架的七大...
  • 最近在做程度登录界面时弹出自动升级提示,已经能够从服务器下载最新版app到本机,但就是安装的时候始终报“解析程序包时出现错误”的提示,但是我直接在下载目录里面打开apk,就可以正常安装,求大神解答,代码如下...
  • Android实现在线更新的过程案例

    千次阅读 2015-03-15 20:50:17
    一、更新软件的准备 在线更新软件的话需要我们有签名的应用,我们需要把签过名之后的软件放入到服务器中,我的如下: 其中apk是有签名的更新版本! updateinfo.html代码如下:{"version":"2.0","description":...
  • Android实现APP自动更新功能

    千次阅读 2015-01-28 17:03:44
    该小程序的特点是,当有更新时,会弹出一个提示框,点击确定,则在通知来创建一个进度条进行下载,点击取消,则取消更新。 以下是详细代码: 1.创建布局文件notification_item.xml,用于在通知栏生成一个进度条和...
  • Retrofit2实现App自动更新

    千次阅读 2016-08-07 21:17:18
    "更新提示" ); builder.setMessage(version_info); // 更新 builder.setPositiveButton( "立即更新" , new DialogInterface.OnClickListener() { @Override public void onClick (DialogInterface ...
  • iOS自动检查更新

    千次阅读 2015-08-17 15:00:34
    我们每天在app store收到新的应用更新通知,打开应用时也是不是弹出更新提示框,自动检查更新这个功能随处可见,虽然作为用户来说老看到这种提示挺烦的,但是作为开发者来说让用户始终更新到最新的版本是最好的,...
  • 今天接到一用户问题,ArcSDE for SQL Server 数据库,利用ArcGIS桌面创建数据集时,提示如下错误: 其实这个错误已经非常明显的告诉了用户,查询的开销比数据库默认设置的小才造成的该错误 “查询开销”是指在...
  • 【Android 应用开发】Android应用的自动更新模块

    万次阅读 多人点赞 2013-11-27 15:05:10
    Android自动更新模块, 适用于任何软件 , 附带该模块的源码, 拷贝即用
  • 在项目中,遇到不能ListView及时更新的问题。写了一个demo,其中也遇到一些问题,一并写出来。前几个月总是有点懒,但是这个月总算是凑够4篇了。代码比较简单,遇到点简单的问题,弄到了现在。好吧,上代码:public ...
  • Android APK版本更新下载

    千次阅读 2017-05-17 20:48:18
    今天做了下APK版本更新的功能。其实关于APK版本更新相关的文章网上挺多的,功能实现上也并不难。基本思路就是讲当前APK的版本号和服务器上保存的最新APK包的版本号进行对比,如果当前版本小于最新版本,则进行下载...
  • Android 版本检测更新

    万次阅读 2016-06-30 15:53:05
    可能有人会问为啥点击更新提示框不消失啊,可以根据自己的情况而定,有的需要强制更新,也是为了方便用户看到下载的进度。我这里只是为了测试一下效果而已。真正的是点击更新以后会在通知栏里面进行显示的 效果就是...
  • 主要介绍Android常用于消息提示的组件:ALertDialog、Toast、Notification的使用场景以及它们的基本用法,探讨一些高级主题,最后总结一些开发过程中常见的问题。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 72,912
精华内容 29,164
关键字:

如何取消更新id提示