編輯:關於Android編程
每一個應用在進入主界面之間應該有一個界面用來顯示公司或者團隊的信息,介紹軟件,並檢查更新,及時提醒用戶更新最新版本,獲得更多更好的用戶體驗。本文將對該實現進行總結,以後用到就不要到處找自己寫的項目了。
習慣上我們把實現該功能的類定義為splashActivity。
進入該界面就應該初始化一些數據,比如復制文件到系統目錄,復制打包的數據庫到系統目錄,檢查軟件版本是否進行更新等。
1、復制文件到系統目錄已經寫成工具類,所以只要獲得文件的源地址和目標地址即可完成復制。如下在android平台下 獲取SD卡的文件目錄代碼如下:
/** * 獲得文件路徑和狀態信息 * * @return */ private List復制文件方法:getFiles() { File path = null; List infos = new ArrayList (); 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); //buffer byte[] b = new byte[512]; while(fr.read(b)!=-1){ bw.write(b); } bw.flush(); flag=true; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(fr != null) try { fr.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(bw != null){ try { bw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return flag; }
File file = new File(getFilesDir(), "xxx.xls");即在android裡面data/data/包名/files目錄下。
通過以上方法即可完成將SD卡的文件復制到應用系統目錄中。
2、復制數據庫到系統目錄
(1)獲得系統文件目錄:
final File file = new File(getFilesDir(), "xxx.db");
(2)獲得位於資產目錄的文件的輸入流
InputStream is = getAssets().open("xxx.db");
getResources()
*讀取文件資源:1.讀取res/raw下的文件資源,通過以下方式獲取輸入流來進行寫操作 · InputStream is =getResources().openRawResource(R.id.filename); 2.讀取assets下的文件資源,通過以下方式獲取輸入流來進行寫操作 · AssetManager am = null; · am = getAssets(); · InputStream is = am.open("filename");
2、讀取拷貝到系統的數據庫,並獲得數據庫引用。然後就可以操作數據庫了。
SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null,
SQLiteDatabase.OPEN_READONLY);
注:拷貝到系統的數據庫文件的路徑為:public static final String path = "/data/data/應用包名/files/數據庫文件";
自己建立的數據庫是databases文件夾下。
工具類如下:
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)首先獲得應用的版本號/** * 獲得應用的版本信息 * @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)同時連接網絡解析服務器的配置文件獲得應用最新的版本號,如下:1)服務器端的xml文件如下2.0 空降新版本,請下載,體驗更多新特性!!! http://192.168.253.1:8080/TouristManager.apk2)連接服務器獲得輸入流解析xml文件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源代碼如下: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()); // 安裝apk installApk(file); finish(); break; case COPYDATA_ERROR: Toast.makeText(getApplicationContext(), "加載數據庫失敗", 0).show(); break; } }; }; @Override protected 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(); } @Override public 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() { @Override public 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() { @Override public void onClick(DialogInterface dialog, int which) { loadMainUI(); } }); builder.create().show(); // builder.show(); } private class CheckVersionTask implements Runnable { @Override public 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); } }工具類源代碼:下載新版APKpackage 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 API 19+ 的設備上可以通過呼叫如下方法隱藏虛擬按鍵: @SuppressLint("NewApi") privat
我們使用控件AutoCompleteTextView 自動提示時,有時需要設置BaseAdapter,設置BaseAdapter時,需要實現Filterable,手動進行
此開源框架官網地址:https://github.com/astuetz/PagerSlidingTabStrip可以理解為配合ViewPager使用的交互式頁面指示器控
Fragment介紹Android在3.0中引入了Fragments的概念,主要目的是用在大屏幕設備上(如平板電腦上)支持更加動態和靈活的UI設計。平板電腦的屏幕要比手機