<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### 配置應用程序在手機桌面顯示的名稱和圖標-AndroidManifest.xml: ~~~ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.liuhao.mobilesafe" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher"《在程序管理列表中顯示的圖標》 ① android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:icon="@drawable/icon5"《在桌面顯示為自己配置的icon5圖標》 ② android:name="com.liuhao.mobilesafe.ui.SplashActivity" android:label="@string/app_name" >《名稱為自己配置的app_name》 ② <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ~~~ 配置后,顯示如圖: ① [![image](https://box.kancloud.cn/2016-02-18_56c5a95037b7d.jpg "image")](http://img.blog.csdn.net/20140926150151180)?[![image](https://box.kancloud.cn/2016-02-18_56c5a9504848c.jpg "image")](http://img.blog.csdn.net/20140926150010078)?? ②[![image](https://box.kancloud.cn/2016-02-18_56c5a9505c2d2.jpg "image")](http://img.blog.csdn.net/20140926150201164) ### 獲取更新的服務器配置流程: [![手機安全衛士](https://box.kancloud.cn/2016-02-18_56c5a950a1ae9.jpg "手機安全衛士")](http://img.blog.csdn.net/20140926150020046) ### 服務器配置: 以tomcat作為服務器,在TOMCAT_HOME/ROOT目錄下新建update.xml文件,在其中添加新版本的相關信息; ~~~ <?xml version="1.0" encoding="utf-8"?> <info> <version>2.0</version> <description>親,最新的版本,速度來下載!</description> <apkurl>http://localhost:18081/newapk.apk</apkurl> </info> ~~~ 在瀏覽器訪問:[http://localhost:18081/update.xml](http://localhost:18081/update.xml "http://localhost:18081/update.xml") [![image](https://box.kancloud.cn/2016-02-18_56c5a950bc9cc.jpg "image")](http://img.blog.csdn.net/20140926150204066) ### xml配置文件的獲取和解析 那么我們的應用程序啟動時就要嘗試到上述地址獲取新版本的信息,同時對xml配置文件進行解析。 #### 那么應用程序如何獲取到上述的版本信息的地址呢?一般在資源文件中以配置文件的方式存儲。 ~~~ config.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="updateurl">http://192.168.1.123:18081/update.xml</string> </resources> ~~~ #### 下面要建立update.xml文件對應的實體類-UpdateInfo.java: ~~~ package com.liuhao.mobilesafe.domain; /** * @author liuhao * 升級信息 */ public class UpdateInfo { String version; String description; String apkurl; public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getApkurl() { return apkurl; } public void setApkurl(String apkurl) { this.apkurl = apkurl; } } ~~~ #### 如何獲取這個config.xml里url對應的文件內容(即[http://192.168.1.123:18081/update.xml](http://localhost:18081/update.xml "http://localhost:18081/update.xml"))? 新建更新信息服務類:UpdateInfoService.java: ~~~ package com.liuhao.mobilesafe.engine; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.content.Context; import com.liuhao.mobilesafe.domain.UpdateInfo; public class UpdateInfoService { private Context context; // 應用程序環境的上下文信息 public UpdateInfoService(Context context) { this.context = context; } /** * @param urlId * 服務器資源路徑對應的id * @return 更新信息 * @throws Exception */ public UpdateInfo getUpdateInfo(int urlId) throws Exception { String path = context.getResources().getString(urlId);// 根據urlId獲取資源文件中對應的內容 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(2000); conn.setRequestMethod("GET"); InputStream is = conn.getInputStream(); //得到url對應的文件流,應該是xml文件流,需要對其進行解析 return UpdateInfoParser.getUpdateInfo(is); } } ~~~ - 知識點:為什么在業務類中不對異常進行捕獲,而是直接拋出了? 向外傳播給更高層處理,以便異常的錯誤原因不丟失,便于排查錯誤或進行捕獲處理。對于異常處理,應該從設計、需要、維護等多個角度綜合考慮,有一個通用準則:千萬別捕獲了異常什么事情都不干,這樣一旦出現異常了,你沒法依據異常信息來排錯。 見:[J2EE系統異常的處理準則](http://blog.csdn.net/bruce_6/article/details/39579243) #### 解析xml文件: 獲取到xml文件流后,要對其進行解析,使用XmlPullParser: XmlPullParser將xml分解成不同的事件類型(EventType) 常用的有: XmlPullParser.END_DOCUMENT:文檔的結束 XmlPullParser.START_DOCUMENT:文檔的開始 XmlPullParser.START_TAG:標簽的開始 XmlPullParser.END_TAG:標簽的結束 XmlPullParser.TEXT :內容 并且該類中的方法主要是用于獲取EventType的內容,以及在EventType之間進行跳轉。 創建解析更新信息的工具服務類UpdateInfoParser: ~~~ package com.liuhao.mobilesafe.engine; import java.io.InputStream; import org.xmlpull.v1.XmlPullParser; import android.util.Xml; import com.liuhao.mobilesafe.domain.UpdateInfo; public class UpdateInfoParser { /** * @param is xml格式的文件輸入流 * @return 解析好的UpdateInfo */ public static UpdateInfo getUpdateInfo(InputStream is) throws Exception{ XmlPullParser parser = Xml.newPullParser(); UpdateInfo info = new UpdateInfo(); // 初始化parser解析器,設置準備對哪個輸入流進行解析 // 這個方法會對parser進行重置,同時會將事件類型(event type)定位到文檔初始位置(START_DOCUMENT) parser.setInput(is, "utf-8"); int type = parser.getEventType(); //獲取當前的EventType while(type != XmlPullParser.END_DOCUMENT){ switch (type) { // 對其中的標簽類型進行處理 case XmlPullParser.START_TAG: if("version".equals(parser.getName())){ String version = parser.nextText(); info.setVersion(version); } else if("description".equals(parser.getName())){ String description = parser.nextText(); info.setDescription(description); } else if("apkurl".equals(parser.getName())){ String apkurl = parser.nextText(); info.setApkurl(apkurl); } break; } type = parser.next(); } return info; } } ~~~ ### 測試 #### 不知道Android如何測試? 1、新建一個Android Test Project,將我們的項目放在測試項目中。 [![image](https://box.kancloud.cn/2016-02-18_56c5a950d0f4a.jpg "image")](http://img.blog.csdn.net/20140926163408847)[![image](https://box.kancloud.cn/2016-02-18_56c5a950eef2f.jpg "image")](http://img.blog.csdn.net/20140926163227828) 2、將test項目中AndroidManifest.xml的<uses-library android:name="android.test.runner" />內容和<instrumentation>節點下的內容拷貝到項目的AndroidManifest.xml中,注意節點的對應。 [![image](https://box.kancloud.cn/2016-02-18_56c5a95111481.jpg "image")](http://img.blog.csdn.net/20140926163411327) 之后,test項目便可以暫時不用了。 3、創建測試類 [![image](https://box.kancloud.cn/2016-02-18_56c5a9512b83f.jpg "image")](http://img.blog.csdn.net/20140926163412388) ~~~ package com.liuhao.mobilesafe.test; import junit.framework.Assert; import com.liuhao.mobilesafe.R; import com.liuhao.mobilesafe.domain.UpdateInfo; import com.liuhao.mobilesafe.engine.UpdateInfoService; import android.test.AndroidTestCase; public class TestGetUpdateInfo extends AndroidTestCase { public void testGetInfo() throws Exception{ UpdateInfoService service = new UpdateInfoService(getContext()); UpdateInfo info = service.getUpdateInfo(R.string.updateurl); Assert.assertEquals("2.0", info.getVersion()); } } ~~~ 4、從服務器上獲取更新信息的配置文件,需要程序有訪問Internet的權限: [![image](https://box.kancloud.cn/2016-02-18_56c5a9514b590.jpg "image")](http://img.blog.csdn.net/20140926163433015) [![image](https://box.kancloud.cn/2016-02-18_56c5a95170790.jpg "image")](http://img.blog.csdn.net/20140928130533450) [![image](https://box.kancloud.cn/2016-02-18_56c5a95185550.jpg "image")](http://img.blog.csdn.net/20140928130534605) 保存,即可。 5、運行測試代碼: [![image](https://box.kancloud.cn/2016-02-18_56c5a951af84d.jpg "image")](http://img.blog.csdn.net/20140928130535665) 出現異常!!!connect failed: ECONNREFUSED (Connection refused) #### 異常處理:java.net.ConnectException android 從tomcat讀取文件時出現以下異常: 08-10 14:53:09.118: W/System.err(12527): java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 8080): connect failed: ECONNREFUSED (Connection refused) 解決方法: String url = "[http://localhost:18081/update.xml](http://localhost:18081/update.xml "http://localhost:18081/update.xml")";? 修改成 String url = "[http://192.168.1.123:18081/update.xml](http://localhost:18081/update.xml "http://localhost:18081/update.xml")"; 主機ip不能使用localhost或者127.0.0.1,使用本機真實ip地址即可。使用ipconfig命令就可以查看到: [![image](https://box.kancloud.cn/2016-02-18_56c5a951c926e.jpg "image")](http://img.blog.csdn.net/20140928130357812) 異常處理后,運行成功! ### 在activity使用業務 所有的業務代碼已經完成,回到splash的activity使用業務! ~~~ package com.liuhao.mobilesafe.ui; import com.liuhao.mobilesafe.R; import com.liuhao.mobilesafe.domain.UpdateInfo; import com.liuhao.mobilesafe.engine.UpdateInfoService; import android.os.Bundle; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.util.Log; import android.view.Menu; import android.view.Window; import android.view.WindowManager; import android.view.animation.AlphaAnimation; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; public class SplashActivity extends Activity { private static final String TAG = "SplashActivity"; private TextView tv_splash_version; private LinearLayout ll_splash_main; private UpdateInfo info; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //取消標題欄 requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.splash); tv_splash_version = (TextView) this.findViewById(R.id.tv_splash_version); ll_splash_main = (LinearLayout) this.findViewById(R.id.ll_splash_main); String versiontext = getVersion(); tv_splash_version.setText(versiontext); if(isNeedUpdate(versiontext)){ Log.i(TAG, "彈出升級對話框"); showUpdateDialog(); } /* AlphaAnimation類:透明度變化動畫類 * AlphaAnimation類是Android系統中的透明度變化動畫類,用于控制View對象的透明度變化,該類繼承于Animation類。 * AlphaAnimation類中的很多方法都與Animation類一致,該類中最常用的方法便是AlphaAnimation構造方法。 * * public AlphaAnimation (float fromAlpha, float toAlpha) 參數說明 fromAlpha:開始時刻的透明度,取值范圍0~1。 toAlpha:結束時刻的透明度,取值范圍0~1。 */ AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f); aa.setDuration(2000); //Animation類的方法,設置持續時間 ll_splash_main.startAnimation(aa); //設置動畫 //完成窗體的全屏顯示 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } private void <span style="color:#FF6666;">showUpdateDialog</span>() { //彈出一個消息框 <span style="color:#FF0000;">AlertDialog.Builder builder = new Builder(this);</span> builder.setIcon(R.drawable.icon5); //設置消息框的標題圖標 builder.setTitle("升級提醒"); //設置消息框的標題 builder.setMessage(info.getDescription()); //設置要顯示的內容 builder.setCancelable(false); //讓用戶不能按后退鍵取消 builder.<span style="color:#FF6666;">setPositiveButton</span>("確定", new OnClickListener() { //設置用戶選擇確定時的按鍵操作 @Override public void onClick(DialogInterface dialog, int which) { Log.i(TAG, "下載pak文件:" + info.getApkurl()); } }); builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.i(TAG, "用戶取消升級,進入程序主界面"); } }); builder.create().show(); } /** * * @param versiontext 當前客戶端的版本信息 * @return 是否需要更新 */ private boolean isNeedUpdate(String versiontext) { UpdateInfoService service = new UpdateInfoService(this); try { info = service.getUpdateInfo(R.string.updateurl); String version = info.getVersion(); if(versiontext.equals(version)){ Log.i(TAG, "版本號相同,無需升級,進入到主界面"); return false; } else{ Log.i(TAG, "版本號不同,需要升級"); return true; } } catch (Exception e) { e.printStackTrace(); /** * Toast使用場景 * 1、需要提示用戶,但又不需要用戶點擊“確定”或者“取消”按鈕。 * 2、不影響現有Activity運行的簡單提示。 */ Toast.makeText(this, "獲取更新信息異常", 2).show();//彈出文本,并保持2秒 Log.i(TAG, "獲取更新信息異常,進入到主界面"); return false; } } @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; } /** * 獲取當前程序的版本號 * @return */ private String getVersion(){ // 獲取一個PackageManager的實例,從而可以獲取全局包信息 PackageManager manager = getPackageManager(); try { // Retrieve overall information about an application package that is installed on the system. PackageInfo info = manager.getPackageInfo(getPackageName(), 0); // The version name of this package, as specified by the <manifest> tag's versionName attribute. return info.versionName; } catch (Exception e) { e.printStackTrace(); return "版本號未知"; } } } ~~~ - isNeedUpdate()方法:調用UpdateInfoService 的getUpdateInfo()方法,來獲取更新信息。同時將服務器端的版本號和當前客戶端的版本號進行對比,并做出是否讓用戶升級的操作。若發現兩個版本號不一致,那么就要提醒用戶進行升級: - 這里調用了showUpdateDialog()方法,在這個方法中,設置界面彈出一個消息框,其中有兩個按鈕:“確定”“取消”,用戶點擊不同的按鈕則對應不同的操作。 #### 異常處理android.os.NetworkOnMainThreadException--多線程問題 一切搞定,以為高枕無憂了,結果還是有問題! log開始報錯了,獲取更新信息異常!!!debug一下,發現Exception:android.os.NetworkOnMainThreadException 這個異常大概意思是在主線程訪問網絡時出的異常。 Android在4.0之前的版本 支持在主線程中訪問網絡,但是在4.0以后對這部分程序進行了優化,也就是說訪問網絡的代碼不能寫在主線程中了。 處理方法:[http://blog.csdn.net/bruce_6/article/details/39640587](http://blog.csdn.net/bruce_6/article/details/39640587)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看