Android项目实战_手机安全卫士splash界面
- 根据代码的类型组织包结构
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.应用自动更新的逻辑图

###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();
贴上对应的源码:
package com.hb.mobilesafe.activities; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; import org.json.JSONObject; 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.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast; import com.hb.demo_mobilesafe.R;
import com.hb.mobilesafe.utils.GetVersonName;
import com.hb.mobilesafe.utils.ReadStrem;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack; public class SplashActivities extends Activity {
protected static final int SUCCESS = 1;
protected static final int ERROR = 2;
private TextView tv_splash_version;
private String localVersion;
private String serviceVerson;
private String apkpath;
private String descritoin;
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SUCCESS:
//判断出的版本号不一样进行升级
builderLoading();
break; case ERROR:
Toast.makeText(SplashActivities.this, "错误信息:"+msg.obj, 0).show();
loadUI();
break;
}
} }; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash);
tv_splash_version = (TextView) findViewById(R.id.tv_splash_version);
SharedPreferences sp=getSharedPreferences("config", MODE_PRIVATE);
//获取开关状态判断是否进行升级提示
boolean tag = sp.getBoolean("update", true);
if(tag){
initDate();
}else{
new Thread(){
public void run() {
SystemClock.sleep(1500);
loadUI();
};
}.start();
}
localVersion = GetVersonName.version(this);
tv_splash_version.setText("版本号:"+localVersion);
//初始化导入数据库到手机
importDataBase("antivirus.db"); }
//初始化导入数据库到手机
private void importDataBase(String fileName) {
File file=new File(getFilesDir(), fileName);
if(file.exists() && file.length()>0){
return;
}
try {
AssetManager assets = getAssets();
InputStream is= assets.open(fileName);
FileOutputStream fs=new FileOutputStream(file);
int len=-1;
byte [] arr=new byte[1024];
while ((len =is.read(arr))!=-1) {
fs.write(arr, 0, len);
}
fs.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} private void initDate() { new Thread(){ private long start;
private Message message;
public void run() {
String path=getResources().getString(R.string.path); try {
URL url = new URL(path);
HttpURLConnection conn =(HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if(code == 200){
InputStream stream = conn.getInputStream();
String json = ReadStrem.readSreamUtil(stream);
JSONObject ob=new JSONObject(json);
serviceVerson = ob.getString("verson");
descritoin = ob.getString("descritoin");
apkpath = ob.getString("apkpath");
start=SystemClock.currentThreadTimeMillis();
/**
* 进行本地版本与服务器版本的对比
*/
if(localVersion.equals(serviceVerson)){
//不需要升级直接调转
// loadUI();
}else{
message = new Message();
message.what=SUCCESS;
handler.sendMessage(message); }
} } catch (Exception e) {
e.printStackTrace();
message = new Message();
message.what=ERROR;
message.obj="code:404";
handler.sendMessage(message); }finally{
long end=SystemClock.currentThreadTimeMillis();
long et=end-start;
if(et>2000){
}else{
SystemClock.sleep(2000-et);
} }
} }.start();
}
/**
* 更新UI
*/
private void loadUI() {
Intent intent=new Intent(SplashActivities.this, HomeActivities.class);
startActivity(intent);
finish();
};
//提示用户升级
private void builderLoading() {
AlertDialog.Builder alert=new Builder(SplashActivities.this);
alert.setTitle("版本升级提示");
alert.setCancelable(false);//设置锁定其他界面点击事件
alert.setMessage(descritoin);
// alert.setIcon(R.drawable.);
alert.setPositiveButton("立刻升级", new OnClickListener() { private ProgressDialog pd; @Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(SplashActivities.this, "升级吧", 0).show();
pd = new ProgressDialog(SplashActivities.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.show(); HttpUtils utils=new HttpUtils();
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//获取SD卡的对象
File sd=Environment.getExternalStorageDirectory();
File file=new File(sd, SystemClock.currentThreadTimeMillis()+".apk");
utils.download(apkpath, file.getAbsolutePath(),new RequestCallBack<File>(){ @Override
public void onFailure(HttpException arg0, String arg1) {
pd.dismiss();
} @Override
public void onSuccess(ResponseInfo<File> arg0) {
pd.dismiss();
//安装APP
Intent intent=new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(
Uri.fromFile(arg0.result),
"application/vnd.android.package-archive");
startActivity(intent);
finish();
} @Override
public void onLoading(long total, long current,
boolean isUploading) {
pd.setMax((int)total);
pd.setProgress((int)current);
super.onLoading(total, current, isUploading);
}
}); }
}
});
alert.setNegativeButton("下次再说", new OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
loadUI();
}
});
alert.show(); } }
布局文件:
<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" />
Android项目实战_手机安全卫士splash界面的更多相关文章
- Android项目实战_手机安全卫士home界面
# 安全卫士主页面# ###1.GridView控件 1.与ListView的使用方式差不多,也要使用数据适配器,通过设置android:numColumns控制显示几列 2.通过指定android: ...
- Android项目实战_手机安全卫士手机防盗界面
#安全卫士手机防盗# ###1.Activity的任务栈 1.类似一个木桶,每层只能放一个木块,我们放入木块和取出木块的时候只能从最上面开始操作 ###2.Android中的坐标系和android:content(内容),并在子View中添加把手和内容的布局```java <Sli ...
- Android项目实战_手机安全卫士进程管理
###1.设备进程信息获取获取设备运行进程 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVI ...
- Android项目实战--手机卫士开发系列教程
<ignore_js_op> banner131010.jpg (71.4 KB, 下载次数: 0) 下载附件 保存到相册 2 分钟前 上传 Android项目实战--手机卫士01- ...
随机推荐
- 疫情控制(codevs 1218)
题目描述 Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为 ...
- HDU1914(稳定婚姻)
http://acm.hdu.edu.cn/showproblem.php?pid=1914 思路:Gale-Shapley算法.算法过程是男士不停地求婚,女士不停地拒绝.在每一轮中,每个尚未订婚的男 ...
- [转]C++回调函数(callback)的使用
原文地址:http://blog.sina.com.cn/s/blog_6568e7880100p77y.html 什么是回调函数(callback) 模块A有一个函数foo,他向模块B传递fo ...
- 不折移动web不腾--开启我的个人Mac之旅
背景,非常久非常久曾经(听过)Linux,瞎玩 Mac mini,而今Linux下开发技能半身不遂,处于放任状态.明明就知道随着时间流逝会越陌生的东西越不想去抓住最后的余温,不知道这算不算放弃,反正迟 ...
- javascript 变量声明 和 作用域
变量的声明 1.变量声明具有提升机制,Javascript在执行时,会把所有的声明都提升到当前作用域前面. 先看一下下面的例子: (function(){ alert(b)//b is not def ...
- LeetCode 438. Find All Anagrams in a String (在字符串中找到所有的变位词)
Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Strings ...
- Linux下的画图软件
Pinta是一款和windows下的画图相类似打一款画图软件,并且它还包含了一些基本的图像编辑工具. 比如:标尺.图层.操作历史记录.图像调整.渲染效果等等,可以满足对图像处理要求不太高的用户的基本需 ...
- 放大的X(杭电2565)
/*放大的X 请你编程画一个放大的'X'. Input 输入数据第一行是一个整数T,表示有T组測试数据: 接下来有T行,每行有一个正奇数n(3 <= n <= 79).表示放大的规格. O ...
- Codeforces Round #272 (Div. 2) D.Dreamoon and Sets 找规律
D. Dreamoon and Sets Dreamoon likes to play with sets, integers and . is defined as the largest p ...
- Android 信息提示——Toast方式
Toast用于向用户显示一些帮助/提示.一下列举了5中样式. 一.默认的效果(显示在屏幕的底部) 代码: Toast.makeText(getApplicationContext(), "默 ...