- 根據代碼的類型組織包結構
1. 界面 com.hb.mobilesafe.activities
2. 服務 com.hb.mobilesafe.services
3. 業務邏輯 com.hb.mobilesafe.engine
4. 資料庫 com.hb.mobilesafe.db
5. 資料庫增删改查 com.hb.mobilesafe.db.dao
6. 工具類 com.hb.mobilesafe.utils
7. 自定義view com.hb.mobilesafe.ui
###3.splash界面的作用
1. 展現産品的logo,提升産品的知名度.
2. 初始化應用程式的資料.
3. 連接配接伺服器,查找可更新的版本,自動更新
4. 使用者操作指南
5. 新版本特性提醒
4.布局檔案的命名規則
SplashActivity--->activity_spalsh.xml
XxxActivity---> activity_xxx.xml
###5.擷取應用程式版本号
//用PackageManager拿到PackageInfo,PackageInfo中的versionName
PackageInfo packinfo = context.getPackageManager().getPackageInfo(
context.getPackageName(), 0);
String version = packinfo.versionName;
###6.源代碼版本控制
- 安裝VisualSVN Server——SVN伺服器,一直下一步即可
- 導入倉庫到伺服器
1.在Repositories處右鍵,選擇Import Existing Repository
2.選擇Copy repository from another location,下一步
3.點選Browse,選擇倉庫路徑,"代碼/代碼倉庫/Repository/mobilesafe",點選下一步
4.點選Import
5.點選Finish,導入完成
- 安裝TortoiseSVN——SVN用戶端,一直下一步即可
1.在想要檢出代碼的地方右鍵,選擇SVN Checkout
2.URL of repository處填https://127.0.0.1/svn/mobilesafe/,位址也可以從SVN伺服器的mobilesafe處右鍵選擇Copy URL to clipboard拷貝
3.Checkout directory出填寫檢出代碼要放的位置,然後點選OK
4.完成代碼的檢出
- 将代碼更新到指定版本
1.mobilesafe檔案夾出右鍵,選擇Update to version
2.點選show log
3.點選左下角的show all
4.選擇要更新的版本,點選OK
5.版本更新完成
###7.應用自動更新的邏輯圖
![](http://i.imgur.com/EU78wXt.png)
###8.擷取伺服器版本号
//擷取伺服器位址
String path = getResources().getString(R.string.url);
URL url = new URL(path);
//建立網絡連接配接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
//送出請求,獲得傳回碼
int code = conn.getResponseCode();
if(code ==200){
//擷取伺服器傳回的流并進行解析
InputStream is = conn.getInputStream();
String result = StreamTools.readStream(is);
//轉化為json并解析出版本号
JSONObject json = new JSONObject(result);
String serverVersion = json.getString("version");
Log.i(TAG,"伺服器版本:"+serverVersion);
}
###9.将流轉化為字元串
public static String readStream(InputStream is) throws IOException{
//ByteArrayOutputStream類是在建立它的執行個體時,程式内部建立一個byte型數組的緩沖區,緩沖區會随着資料的不斷寫入而自動增長。可使用 toByteArray()和 toString()擷取資料
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while((len = is.read(buffer))!=-1){
baos.write(buffer, 0, len);
}
is.close();
return baos.toString();
}
###10.彈出對話框
1.使用AlertDialog.Builder
2.設定标題、資訊、點選事件等
3.調用show方法顯示出來,調用dismiss方法消失
###11.下載下傳apk
1.使用開源架構xUtils
2.使用HttpUtils的download方法,填入三個參數:伺服器下載下傳位址,手機中的存儲位置、回調事件
3.回調事件中有三個常用的方法:onSuccess下載下傳成功、onFailure下載下傳失敗、onLoading更新下載下傳進度
xUtils補充
http://my.oschina.net/u/1171837/blog/147544 作者部落格
###12.安裝apk
1.調用系統的安裝apk的界面,傳入對應的參數
2.具體實作方式
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(
Uri.fromFile(fileinfo.result),
"application/vnd.android.package-archive");
startActivity(intent);
###13.應用程式的覆寫安裝要滿足的條件
1. 兩個版本簽名一緻
2. 兩個版本包名一緻
###14.跑馬燈效果的TextView
1. 系統的TextView不能擷取焦點,使用自定義控件
2. 繼承TextView控件,重寫isFocused方法,直接傳回true,讓其擷取焦點
3. 設定android:ellipsize="marquee"
###15.旋轉的弘博logo
1. 使用系統提供的屬性動畫
2. 具體實作方式
ObjectAnimator oa = ObjectAnimator.ofFloat(iv_home_logo, "rotationY",
45, 90, 135, 180, 225, 270, 315);
oa.setDuration(3000);
oa.setRepeatCount(ObjectAnimator.INFINITE);
oa.setRepeatMode(ObjectAnimator.RESTART);
oa.start();
貼上對應的源碼:
1 package com.hb.mobilesafe.activities;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.net.HttpURLConnection;
8 import java.net.URL;
9
10 import org.json.JSONObject;
11
12 import android.app.Activity;
13 import android.app.AlertDialog;
14 import android.app.AlertDialog.Builder;
15 import android.app.ProgressDialog;
16 import android.content.DialogInterface;
17 import android.content.DialogInterface.OnClickListener;
18 import android.content.Intent;
19 import android.content.SharedPreferences;
20 import android.content.res.AssetManager;
21 import android.net.Uri;
22 import android.os.Bundle;
23 import android.os.Environment;
24 import android.os.Handler;
25 import android.os.Message;
26 import android.os.SystemClock;
27 import android.view.Window;
28 import android.widget.TextView;
29 import android.widget.Toast;
30
31 import com.hb.demo_mobilesafe.R;
32 import com.hb.mobilesafe.utils.GetVersonName;
33 import com.hb.mobilesafe.utils.ReadStrem;
34 import com.lidroid.xutils.HttpUtils;
35 import com.lidroid.xutils.exception.HttpException;
36 import com.lidroid.xutils.http.ResponseInfo;
37 import com.lidroid.xutils.http.callback.RequestCallBack;
38
39 public class SplashActivities extends Activity {
40 protected static final int SUCCESS = 1;
41 protected static final int ERROR = 2;
42 private TextView tv_splash_version;
43 private String localVersion;
44 private String serviceVerson;
45 private String apkpath;
46 private String descritoin;
47 private Handler handler=new Handler(){
48 public void handleMessage(android.os.Message msg) {
49 switch (msg.what) {
50 case SUCCESS:
51 //判斷出的版本号不一樣進行更新
52 builderLoading();
53 break;
54
55 case ERROR:
56 Toast.makeText(SplashActivities.this, "錯誤資訊:"+msg.obj, 0).show();
57 loadUI();
58 break;
59 }
60 }
61
62
63 };
64
65 @Override
66 protected void onCreate(Bundle savedInstanceState) {
67 super.onCreate(savedInstanceState);
68 requestWindowFeature(Window.FEATURE_NO_TITLE);
69 setContentView(R.layout.activity_splash);
70 tv_splash_version = (TextView) findViewById(R.id.tv_splash_version);
71 SharedPreferences sp=getSharedPreferences("config", MODE_PRIVATE);
72 //擷取開關狀态判斷是否進行更新提示
73 boolean tag = sp.getBoolean("update", true);
74 if(tag){
75 initDate();
76 }else{
77 new Thread(){
78 public void run() {
79 SystemClock.sleep(1500);
80 loadUI();
81 };
82 }.start();
83 }
84 localVersion = GetVersonName.version(this);
85 tv_splash_version.setText("版本号:"+localVersion);
86 //初始化導入資料庫到手機
87 importDataBase("antivirus.db");
88
89 }
90 //初始化導入資料庫到手機
91 private void importDataBase(String fileName) {
92 File file=new File(getFilesDir(), fileName);
93 if(file.exists() && file.length()>0){
94 return;
95 }
96 try {
97 AssetManager assets = getAssets();
98 InputStream is= assets.open(fileName);
99 FileOutputStream fs=new FileOutputStream(file);
100 int len=-1;
101 byte [] arr=new byte[1024];
102 while ((len =is.read(arr))!=-1) {
103 fs.write(arr, 0, len);
104 }
105 fs.close();
106 is.close();
107 } catch (IOException e) {
108 // TODO Auto-generated catch block
109 e.printStackTrace();
110 }
111 }
112
113 private void initDate() {
114
115 new Thread(){
116
117 private long start;
118 private Message message;
119 public void run() {
120 String path=getResources().getString(R.string.path);
121
122 try {
123 URL url = new URL(path);
124 HttpURLConnection conn =(HttpURLConnection) url.openConnection();
125 conn.setConnectTimeout(5000);
126 conn.setRequestMethod("GET");
127 int code = conn.getResponseCode();
128 if(code == 200){
129 InputStream stream = conn.getInputStream();
130 String json = ReadStrem.readSreamUtil(stream);
131 JSONObject ob=new JSONObject(json);
132 serviceVerson = ob.getString("verson");
133 descritoin = ob.getString("descritoin");
134 apkpath = ob.getString("apkpath");
135 start=SystemClock.currentThreadTimeMillis();
136 /**
137 * 進行本地版本與伺服器版本的對比
138 */
139 if(localVersion.equals(serviceVerson)){
140 //不需要更新直接調轉
141 // loadUI();
142 }else{
143 message = new Message();
144 message.what=SUCCESS;
145 handler.sendMessage(message);
146
147
148 }
149 }
150
151 } catch (Exception e) {
152 e.printStackTrace();
153 message = new Message();
154 message.what=ERROR;
155 message.obj="code:404";
156 handler.sendMessage(message);
157
158 }finally{
159 long end=SystemClock.currentThreadTimeMillis();
160 long et=end-start;
161 if(et>2000){
162 }else{
163 SystemClock.sleep(2000-et);
164 }
165
166 }
167 }
168
169
170 }.start();
171 }
172 /**
173 * 更新UI
174 */
175 private void loadUI() {
176 Intent intent=new Intent(SplashActivities.this, HomeActivities.class);
177 startActivity(intent);
178 finish();
179 };
180 //提示使用者更新
181 private void builderLoading() {
182 AlertDialog.Builder alert=new Builder(SplashActivities.this);
183 alert.setTitle("版本更新提示");
184 alert.setCancelable(false);//設定鎖定其他界面點選事件
185 alert.setMessage(descritoin);
186 // alert.setIcon(R.drawable.);
187 alert.setPositiveButton("立刻更新", new OnClickListener() {
188
189 private ProgressDialog pd;
190
191 @Override
192 public void onClick(DialogInterface dialog, int which) {
193 Toast.makeText(SplashActivities.this, "更新吧", 0).show();
194 pd = new ProgressDialog(SplashActivities.this);
195 pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
196 pd.show();
197
198 HttpUtils utils=new HttpUtils();
199 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
200 //擷取SD卡的對象
201 File sd=Environment.getExternalStorageDirectory();
202 File file=new File(sd, SystemClock.currentThreadTimeMillis()+".apk");
203 utils.download(apkpath, file.getAbsolutePath(),new RequestCallBack<File>(){
204
205 @Override
206 public void onFailure(HttpException arg0, String arg1) {
207 pd.dismiss();
208 }
209
210 @Override
211 public void onSuccess(ResponseInfo<File> arg0) {
212 pd.dismiss();
213 //安裝APP
214 Intent intent=new Intent();
215 intent.setAction("android.intent.action.VIEW");
216 intent.addCategory("android.intent.category.DEFAULT");
217 intent.setDataAndType(
218 Uri.fromFile(arg0.result),
219 "application/vnd.android.package-archive");
220 startActivity(intent);
221 finish();
222 }
223
224 @Override
225 public void onLoading(long total, long current,
226 boolean isUploading) {
227 pd.setMax((int)total);
228 pd.setProgress((int)current);
229 super.onLoading(total, current, isUploading);
230 }
231 });
232
233 }
234 }
235 });
236 alert.setNegativeButton("下次再說", new OnClickListener() {
237
238 @Override
239 public void onClick(DialogInterface dialog, int which) {
240 loadUI();
241 }
242 });
243 alert.show();
244
245 }
246
247
248 }
布局檔案:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/splash"
tools:context="${relativePackage}.${activityClass}" >
<TextView
android:id="@+id/tv_splash_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="15dip"
android:textSize="16sp"
android:text="版本号:1.0" />
</RelativeLayout>
給上這個項目中所需的所有權限不懂的可以百度一下:
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<!-- 短信備份 -->
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
<uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
轉載于:https://www.cnblogs.com/boket/p/6991375.html