標籤:android 使用者體驗 對話方塊
每一個應用在進入主介面之間應該有一個介面用來顯示公司或者團隊的資訊,介紹軟體,並檢查更新,及時提醒使用者更新最新版本,獲得更多更好的使用者體驗。本文將對該實現進行總結,以後用到就不要到處找自己寫的項目了。
習慣上我們把實現該功能的類定義為splashActivity。
進入該介面就應該初始化一些資料,比如複製檔案到系統目錄,複製打包的資料庫到系統目錄,檢查軟體版本是否進行更新等。
1、複製檔案到系統目錄已經寫成工具類,所以只要獲得檔案的源地址和目標地址即可完成複製。如下在android平台下 擷取SD卡的檔案目錄代碼如下:
/** * 獲得檔案路徑和狀態資訊 * * @return */private List<MyFileInfo> getFiles() {File path = null;List<MyFileInfo> infos = new ArrayList<MyFileInfo>();MyFileInfo info = null;// 判斷SD卡是否存在可用if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {path = Environment.getExternalStorageDirectory();File[] files = path.listFiles();for (File file : files) {// 把路徑如入集合中if (file.getPath() != null) {info = new MyFileInfo();info.setPath(file.getPath());infos.add(info);info = null;}}} else {Toast.makeText(FileSearchActivity.this, "SD卡不可用!", 300).show();}return infos;}複製檔案方法:
/** * @warning The name of file must be end with .xls * @param res The resource file * @param des The destination * @return * @throws FileNotFoundException */public static boolean toCopy(String res,String des){boolean flag=false;//輸入源檔案File file = new File(res) ;FileInputStream fr=null;//複製目標檔案File desFile = new File(des);FileOutputStream bw=null;try {fr = new FileInputStream(file);bw = new FileOutputStream(desFile);//bufferbyte[] b = new byte[512];while(fr.read(b)!=-1){bw.write(b);}bw.flush();flag=true;} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(fr != null)try {fr.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}if(bw != null){try {bw.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}return flag;}
擷取android應用系統目錄的方法:
File file = new File(getFilesDir(), "xxx.xls");即在android裡面data/data/包名/files目錄下。
通過以上方法即可完成將SD卡的檔案複製到應用系統目錄中。
2、複製資料庫到系統目錄
<p>(1)獲得系統檔案目錄:</p><p><span style="color:rgb(127, 0, 85);">final</span> File file = <span style="color:rgb(127, 0, 85);">new</span> File(getFilesDir(), <span style="color:rgb(42, 0, 255);">"xxx.db"</span>);</p><p>(2)獲得位於資產目錄的檔案的輸入資料流</p><p>InputStream is = getAssets().open(<span style="color:rgb(42, 0, 255);">"xxx.db"</span>);</p><p>getResources()</p><p>*<span style="font-family:宋體;">讀取檔案資源:</span><span style="font-family:Times New Roman;">1.</span><span style="font-family:宋體;">讀取</span><span style="font-family:Times New Roman;">res/raw</span><span style="font-family:宋體;">下的檔案資源,通過以下方式擷取輸入資料流來進行寫操作</span>· <span style="font-family:Times New Roman;">InputStream is =getResources().openRawResource(R.id.filename); </span>2.<span style="font-family:宋體;">讀取</span><span style="font-family:Times New Roman;">assets</span><span style="font-family:宋體;">下的檔案資源,通過以下方式擷取輸入資料流來進行寫操作</span>· <span style="font-family:Times New Roman;">AssetManager am = null; </span>· <span style="font-family:Times New Roman;">am = getAssets(); </span>· <span style="font-family:Times New Roman;">InputStream is = am.open("filename"); </span></p><p> </p><p> </p><p>2<span style="font-family:宋體;">、讀取拷貝到系統的資料庫,並獲得資料庫引用。然後就可以操作資料庫了。</span></p><p>SQLiteDatabase db = SQLiteDatabase.openDatabase(<span style="color:rgb(0,0,192);">path</span>, <span style="color:rgb(127,0,85);">null</span>,</p><p>SQLiteDatabase.<span style="color:rgb(0,0,192);">OPEN_READONLY</span>);</p><p> </p><p><span style="background:rgb(255,255,0);">註:拷貝到系統的資料庫檔案的路徑為:</span><span style="color:rgb(127, 0, 85);">public</span> <span style="color:rgb(127, 0, 85);">static</span> <span style="color:rgb(127, 0, 85);">final</span> String <span style="color:rgb(0, 0, 192);">path</span> = <span style="color:rgb(42, 0, 255);">"/data/data/</span><span style="color:rgb(42, 0, 255);">應用程式套件名</span><span style="color:rgb(42, 0, 255);">/files/</span><span style="color:rgb(42, 0, 255);">資料庫檔案</span><span style="color:rgb(42, 0, 255);">"</span>;</p><p>自己建立的資料庫是databases<span style="font-family:宋體;">檔案夾下。</span></p><p> </p>
工具類如下:
<pre name="code" class="java">public class CopyFileToSystem {public CopyFileToSystem() {// TODO Auto-generated constructor stub}/** * 把檔案拷貝到系統檔案夾 * @param in * @param destPath */public static void copyFile(InputStream in,String destPath){//目標檔案File file=new File(destPath);FileOutputStream fos=null;try {fos=new FileOutputStream(file);int len=0;byte[] buffer=new byte[1024];while((len=in.read(buffer))!=-1){fos.write(buffer,0,len);}fos.flush();fos.close();in.close();} catch (Exception e) {} }}
3、檢查更新
(1)首先獲得應用的版本號碼
<pre name="code" class="java">/** * 獲得應用的版本資訊 * @return 應用的版本號碼 */private String getAppVersion(){PackageManager pm=getPackageManager();PackageInfo info=null;try {info=pm.getPackageInfo(getPackageName(),0);if(info!=null){ return info.versionName;}} catch (NameNotFoundException e) {e.printStackTrace();}return "";}
(2)同時串連網路解析伺服器的設定檔獲得應用最新的版本號碼,如下:
<span style="white-space:pre"></span>1)伺服器端的xml檔案如下
<?xml version="1.0" encoding="utf-8"?><info><version>2.0</version><description>空降新版本,請下載,體驗更多新特性!!!</description><apkurl>http://192.168.253.1:8080/TouristManager.apk</apkurl></info>
<span style="white-space:pre"></span>2)串連伺服器獲得輸入資料流解析xml檔案
<span style="white-space:pre"></span><pre name="code" class="java">public class UpdateInfoParser {/** * 解析伺服器返回的更新資訊 * @param is 伺服器返回的流 * @return 如果發生異常 返回null; */public static UpdateInfo getUpdateInfo(InputStream is) {try {XmlPullParser parser = Xml.newPullParser();parser.setInput(is, "utf-8");int type = parser.getEventType();UpdateInfo info = null;while(type!=XmlPullParser.END_DOCUMENT){switch (type) {case XmlPullParser.START_TAG:if("info".equals(parser.getName())){info = new UpdateInfo();}else if("version".equals(parser.getName())){info.setVersion(parser.nextText());}else if("description".equals(parser.getName())){info.setDescription(parser.nextText());}else if("apkurl".equals(parser.getName())){info.setApkurl(parser.nextText());}break;}type = parser.next();}return info;} catch (Exception e) {e.printStackTrace();return null;}}}
整個splash原始碼如下:
<pre name="code" class="html">package com.example.ehrmanager;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import android.app.Activity;import android.app.AlertDialog;import android.app.AlertDialog.Builder;import android.app.ProgressDialog;import android.content.DialogInterface;import android.content.DialogInterface.OnClickListener;import android.content.Intent;import android.content.SharedPreferences;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.content.res.Resources.NotFoundException;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.Menu;import android.view.animation.AlphaAnimation;import android.widget.TextView;import android.widget.Toast;import com.example.ehrmanager.domain.UpdateInfo;import com.example.ehrmanager.utils.DownLoadUtil;import com.example.ehrmanager.utils.UpdateInfoParser;public class SplashActivity extends Activity {private TextView mTVversion;//顯示應用的版本private String mVersion;//應用的版本public static final int PARSE_XML_ERROR = 10;public static final int PARSE_XML_SUCCESS = 11;public static final int SERVER_ERROR = 12;public static final int URL_ERROR = 13;public static final int NETWORK_ERROR = 14;private static final int DOWNLOAD_SUCCESS = 15;private static final int DOWNLOAD_ERROR = 16;protected static final String TAG = "SplashActivity";private static final int COPYDATA_ERROR = 17;private UpdateInfo updateInfo;private ProgressDialog pd;// 下載進度的對話方塊private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {switch (msg.what) {case PARSE_XML_ERROR:Toast.makeText(getApplicationContext(), "解析xml失敗", 0).show();// 進入程式主介面loadMainUI();break;case SERVER_ERROR:Toast.makeText(getApplicationContext(), "伺服器異常", 0).show();// 進入程式主介面loadMainUI();break;case URL_ERROR:Toast.makeText(getApplicationContext(), "伺服器位址異常", 0).show();// 進入程式主介面loadMainUI();break;case NETWORK_ERROR:Toast.makeText(getApplicationContext(), "網路異常", 0).show();// 進入程式主介面loadMainUI();break;case PARSE_XML_SUCCESS:if (getAppVersion().equals(updateInfo.getVersion())) {// 進入程式主介面Log.i(TAG, "版本號碼相同,進入主介面");loadMainUI();} else {Log.i(TAG, "版本號碼不相同,彈出來升級提示對話方塊");showUpdateDialog();}break;case DOWNLOAD_ERROR:Toast.makeText(getApplicationContext(), "下載失敗", 0).show();// 進入程式主介面loadMainUI();break;case DOWNLOAD_SUCCESS:File file = (File) msg.obj;Log.i(TAG, "安裝apk" + file.getAbsolutePath());// 安裝apkinstallApk(file);finish();break;case COPYDATA_ERROR:Toast.makeText(getApplicationContext(), "載入資料庫失敗", 0).show();break;}};};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);intiViews();}/** * 初始化組件 */private void intiViews() {setContentView(R.layout.activity_splash);mTVversion=(TextView)this.findViewById(R.id.app_version);mVersion=getAppVersion();//獲得應用的版本mTVversion.setText(mVersion);// 串連伺服器 檢查版本更新.new Thread(new CheckVersionTask()).start();AlphaAnimation aa = new AlphaAnimation(0.2f, 1.0f);aa.setDuration(2000);findViewById(R.id.rl_splash).startAnimation(aa);}/** * 獲得應用的版本資訊 * @return 應用的版本號碼 */private String getAppVersion(){PackageManager pm=getPackageManager();PackageInfo info=null;try {info=pm.getPackageInfo(getPackageName(),0);if(info!=null){ return info.versionName;}} catch (NameNotFoundException e) {e.printStackTrace();}return "";}/** * 進入主介面 */private void loadMainUI(){Intent intent=new Intent(SplashActivity.this,HomeActivity.class);startActivity(intent);this.finish();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.splash, menu);return true;}/** * 自動升級的提示對話方塊 */protected void showUpdateDialog() {AlertDialog.Builder builder = new Builder(this);builder.setTitle("升級提醒");builder.setMessage(updateInfo.getDescription());builder.setPositiveButton("確定", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {String apkurl = updateInfo.getApkurl();pd = new ProgressDialog(SplashActivity.this);pd.setTitle("升級操作");pd.setMessage("正在下載...");pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);pd.show();Log.i(TAG, "下載後安裝:" + apkurl);final File file = new File(Environment.getExternalStorageDirectory(), DownLoadUtil.getFileName(apkurl));// 判斷sd卡是否可用,只有可用狀態.if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {new Thread() {public void run() {File savedFile = DownLoadUtil.download(updateInfo.getApkurl(),file.getAbsolutePath(), pd);Message msg = Message.obtain();if (savedFile != null) {// 下載成功msg.what = DOWNLOAD_SUCCESS;msg.obj = savedFile;} else {// 下載失敗msg.what = DOWNLOAD_ERROR;}handler.sendMessage(msg);pd.dismiss();};}.start();} else {Toast.makeText(getApplicationContext(), "sd卡不可用", 0).show();loadMainUI();}}});builder.setNegativeButton("取消", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {loadMainUI();}});builder.create().show();// builder.show();}private class CheckVersionTask implements Runnable {@Overridepublic void run() {SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);boolean isupdate = sp.getBoolean("update", true);if (!isupdate) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}loadMainUI();return;}long startTime = System.currentTimeMillis();Message msg = Message.obtain();try {URL url = new URL(getResources().getString(R.string.serverurl));HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(1500);int code = conn.getResponseCode();if (code == 200) {InputStream is = conn.getInputStream();updateInfo = UpdateInfoParser.getUpdateInfo(is);if (updateInfo == null) {// TODO:解析xml失敗msg.what = PARSE_XML_ERROR;} else {// 解析成功msg.what = PARSE_XML_SUCCESS;}} else {// TODO:伺服器內部錯誤.msg.what = SERVER_ERROR;}} catch (MalformedURLException e) {msg.what = URL_ERROR; // http://e.printStackTrace();} catch (NotFoundException e) {msg.what = URL_ERROR; //e.printStackTrace();} catch (IOException e) {msg.what = NETWORK_ERROR;e.printStackTrace();} finally {long endTime = System.currentTimeMillis();long dTime = endTime - startTime;if (dTime < 2000) {try {Thread.sleep(2000 - dTime);} catch (InterruptedException e) {e.printStackTrace();}}handler.sendMessage(msg);}}}/** * 安裝一個apk檔案 * * @param file */protected void installApk(File file) {Intent intent = new Intent();intent.setAction("android.intent.action.VIEW");intent.addCategory("android.intent.category.DEFAULT");intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");startActivity(intent);}}
工具類原始碼:
下載新版APK
<pre name="code" class="java">package com.example.ehrmanager.utils;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import android.app.ProgressDialog;public class DownLoadUtil {/** * 下載檔案操作 * * @param serverPath * 伺服器檔案的路徑 * @param savedPath * 本地儲存的路徑 * @param pd 進度條對話方塊 * @return 下載成功 返迴文件對象 下載失敗 返回null */public static File download(String serverPath, String savedPath, ProgressDialog pd) {try {URL url = new URL(serverPath);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(5000);conn.setRequestMethod("GET");int code = conn.getResponseCode();if (code == 200) {pd.setMax(conn.getContentLength());InputStream is = conn.getInputStream();File file = new File(savedPath);FileOutputStream fos = new FileOutputStream(file);byte[] buffer = new byte[1024];int len = 0;int total = 0;while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);total +=len;pd.setProgress(total);Thread.sleep(20);}fos.flush();fos.close();is.close();return file;} else {return null;}} catch (Exception e) {e.printStackTrace();return null;}}/** * 擷取伺服器檔案的名稱 * @param serverPath * @return */public static String getFileName(String serverPath){return serverPath.substring(serverPath.lastIndexOf("/")+1);}}
Android應用檢查更新總結