01_项目介绍_20
演示项目功能;
1、对前面知识的综合应用,复习基础一遍。
2、熟悉代码,找到敲代码的感觉;
3、每天会有1000-1500行代码量;这几天下来一共就会有1万多行代码量。
4、大学软件工程的学生毕业要求3-5万行的代码量。10几天完成三分之一、五分之一;
5、版本控制,每一天的代码用版本控制起来,可以看到每天的代码;
6、演示程序代码。
7、演示功能有:
启动页面
主页
手机防盗(注意:演示时模拟器要提前设置有联系人);
通讯卫士:黑名单的管理:电话拦截、短信拦截的演示;
软件管理:列出系统的所以软件,启动软件、卸载软件、系统的卸载失败(需要root权 限这个后面也会介绍)
进程管理:列出系统中正在运行的程序;演示杀死软件
窗口小部件:添加桌面;
流量统计:模拟器并不支持,在真机上才能演示,只做个UI效果;
手机杀毒:检查手机安装的软件,发现那个是病毒,提醒用户就杀掉;
系统优化:清除系统的垃圾,刚开始运行,没用多余数据;
高级工具:归属地查询;常用号码查询;短信备份;
02_Svn服务器的使用_20
1、演示svn安装好的样子;
2、查看提交了哪些文件,修改了哪些代码
3、基于已经存在的RepositoriesX代码仓库,创建代码创库;
4、建立创库RepositoriesX代码仓库,导入代码;----基于已有的创库;
5、基于创库建立新MobileSafe代码工程;----建立一个新的工程;
03_代码组织结构_10
1、按照模块 组织代码的包结构。 业务之间彼此独立;
办公软件
-- 开会 com.itheima.meeting
-- 发放工资 com.itheima.money
-- 出差 com.itheima.travel
车载电脑
-- 多媒体
-- 导航
-- 领航
2、按照代码的类型组织包结构;
界面 com.itheima.mobilesafe.activies
自定义UI com.itheima.mobilesafe.ui
业务逻辑代码 com.itheima.mobilesafe.engine 数据引擎业务逻辑 获取解析数据
持久化 com.itheima.mobilesafe.db
com.itheima.mobilesafe.db.dao
广播接收者 com.itheima.mobilesafe.receiver
长期在后台运行 com.itheima.mobilesafe.service
公用的api工具类com.itheima.mobilesafe.utils
04_Splash界面的UI_20
第一: splash界面的作用
1、用来展现产品的Logo;
2、应用程序初始化的操作;
3、检查应用程序的版本;
4、检查当前应用程序是否合法注册;
第二:写界面
android:id="@+id/tv_splash_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textStyle="bold"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="0.2"
android:shadowColor="#ffff00"
android:text="版本:1.0"
android:textSize="16sp"
android:layout_centerInParent="true"
第三:动态获取程序的版本名称的方法
/**
* 得到应用程序的版本号
*/
public String getAppVersion(){
PackageManager pm = getPackageManager();
try {
PackageInfo info = pm.getPackageInfo(getPackageName(), 0);
return info.versionName;
} catch (NameNotFoundException e) {
e.printStackTrace();
//不可能发生;
return "";
}
}
运行演示看效果。
知识拓展:http://blog.youkuaiyun.com/qinjuning/article/details/6867806
http://www.umindex.com/#android_system
4、演示提交代码;
05_连接服务器获取更新信息_50
1、查看当前升级提醒对话框效果图
2、画升级流程图
3、到webservice里去写json文件:update.json
4、Anddroid工程添加联网权限:android.permission.INTERNET
5、在子线程钟请求服务器代码checkVersion()。
6、请求网络的代码
URL url = new URL(getString(R.string.serviceurl));
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
7、参照一个解析流的类StreamTools
8、解析JSON
JSONObject obj = new JSONObject(result);
//服务器的版本号
String version = (String) obj.get("version");
description = (String) obj.get("description");
apkurl = (String) obj.get("apkurl");
9、用Handler更新信息
10、创建主页面HomeActivity和布局文件
11、写延迟2秒进入主页面代码
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
long dTime = endTime - startTime;
if(dTime<2000){
try {
Thread.sleep(2000-dTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
12、添加AlphaAnimation动画效果
AlphaAnimation aa = new AlphaAnimation(0.3f, 1.0f);
findViewById(R.id.rl_root_splash).startAnimation(aa);
13、测试异常况好不好用
14、提交代码到SVN服务器
06_应用程序的签名_30
准备:webservice 上放置一个正式签名的应用
1、显示更新对话框showUpdateDialog();
protected void showUpdateDialog() {
AlertDialog.Builder build = new Builder(this);
build.setTitle("发现新版本");
build.setMessage(description);
build.setNegativeButton("立刻升级", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//升级的代码;
};
});
build.setPositiveButton("下次再说", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
enterHome();
}
});
build.show();
2、下载功能,用到afinal下载框架:FinalHttp
判断SDcard代码:
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
下载代码
FinalHttp http = new FinalHttp();
//mnt/sdcard/updata.apk
Http.download();
更新进度代码
int progress = (int) (current * 100/count);
tv_splash_updateinfo.setText("下载了:"+progress+"%");
3、添加SDcard写权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3、调用系统安装工具安装APK
private void installAPK(File t) {
Intent intent = new Intent(); intent.setAction("android.intent.action.INSTALL_PACKAGE" ); intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(t), "application/vnd.android.package-archive");
startActivity(intent);
}
4、安装失败
5、引入apk签名
在Android手机里不允许有两个应用程序有相同的包名;
假设A应用的包名:com.itheima.mobilesafeA;
A应用已经在系统中存在了。
这个时候再去安装一个应用B ,他的报名也叫 con.itheima.mobilesafeA
系统就会去检查这两应用的签名是否相同。如果相同,B会把A给覆盖安装掉;
如果不相同 B安装失败;
要想自动安装成功,必须保证应用程序不同版本的签名完成一样。
6、签名演示
7、签名两个应用1.0和2.0,并演示升级不成功和升级成功:如果签名搞丢了怎么办
07_Splash界面的细节_6
准备:启动webserver服务器
1、显示4.0的样式:方式是去掉功能清单里的Activity对应的android:theme;
放到application里面;
2、当splash页面弹出升级提示框过滤点击返回的是两种方式:
一、builder.setCancelable(false);
二、设置setOnCancelListener 当触屏的时候直接进入主页面
08_两种上下文的区别_8
对话框是Activity的一部分。
对话框是挂载在Activity上面的 。
如果Activity不存在,对话框就不能被创建。
Activity 实际上是应用程序context上下文的一个子集。
子类有的东西父类不一定有
父类有的东西子类一定有
getApplicationContext();生命周期长,只要应用还存活它就存在;
this 生命周期短,只要Activity不存在了,系统就会回收;
其中:getBaseContext(),getApplication(),getApplicationContext();
都不能放在AlertDialog做上下文;
getApplicationContext() 使用场景是比如频繁需要操作的数据库
推荐用法:Activity.this
09_应用程序主界面_15
1、画图九宫格和列表
功能列表颜色值:#8866ff00
textSize:22sp
<GridView
android:id="@+id/gv_home_gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:verticalSpacing="15dip" />
Names:手机防盗、通讯卫士、软件管理
进程管理、流量统计、手机杀毒
缓存清理、高级工具、设置中心
10_自定义可以滚动TextView_10;
写完主页面后
Button 有文字滚动
<Button
android:focusableInTouchMode="true"
android:textColor="#000000"
android:layout_width="fill_parent"
android:singleLine="true"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:layout_gravity="center_horizontal"
android:text="欢迎使用手机卫士,呵呵欢迎使用手机卫士"
android:textSize="16sp"
/>
FocusedTextView
<com.itheima.mobilesafe.ui.FocusedTextView
android:textColor="#000000"
android:layout_width="fill_parent"
android:singleLine="true"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:layout_gravity="center_horizontal"
android:text="欢迎使用手机卫士,呵呵欢迎使用手机卫士,呵呵欢迎使用手机卫士,呵呵欢迎使用手机卫士,呵呵"
android:textSize="16sp"
/>
11_自动更新的组合控件_50
准备:开启webserver服务器
1、每次都升级消耗多余的流量
2、在主页面增加点击事件进入设置类;
3、创建SettingActivity类,并在功能清单文件配置;
4、SettingActivity的布局文件,基于activity_home.xml修改;
5、运行可以点击进入设置中心;
6、开始写设置里的布局文件了,参照系统的设置里的“位置服务”
7、布局文件
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dip" >
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginTop="5dip"
android:text="更新设置"
android:textColor="#000000"
android:textSize="22sp" />
<TextView
android:id="@+id/tv_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv_title"
android:layout_marginLeft="5dip"
android:text="自动升级已经关闭"
android:textColor="#88000000"
android:textSize="15sp" />
<CheckBox
android:id="@+id/cb_status"
android:layout_centerVertical="true"
android:layout_marginRight="10dip"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<View
android:layout_alignParentBottom="true"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:background="#66000000"
android:layout_width="fill_parent"
android:layout_height="0.2dip"/>
</RelativeLayout>
8、抽取出来单独类SettingItemView
9、单独的布局文件setting_item_view.xml
10、演示多个设置条目当时的方便;
11、相应组合控件的点击事件;
12、判断组合控件是否被选中,其实就是CheckBox的状态是否被选中;
13、在SettingItemView 增加isChecked()、setChecked();方法;并演示
14、在在SettingItemView 增加setDesc()方法;并演示;
15、演示并处理CheckBox的点击事件---解决方案:禁用点击事件;
android:clickable=”false”
android:focusable=”false”
16、记录选中状态,并在进入的时候读取保存的状态;
17、在SplashActivity根据是否开启升级而相应的是否升级;
18、延迟两秒进入主页面的代码;
//停留2秒后进入主页面;
handler.postDelayed(new Runnable() {
@Override
public void run() {
enterHome();
}
}, 2000);
12_定义自定义控件的属性_25
1、演示当前扩展的麻烦性,再增加自定义组合控件的使用情境;
2、去掉setting_item_view.xml的文字,运行演示;
3、在SettingItemView里加自定义组合控件的标题方法setTitle();
4、在SettingActivity代码里写另外一个设置条的标题和描述信息赋值;
5、参照系统控件TextView讲解系控件的属性特点;
6、自定义标题属性title、描述打开属性descon、描述关闭属性descoff;
7、参照系统的命名空间写自定义的命名空间,并演示删除系统命名空间报错;
8、讲解自定命名空间;
9、演示运行时报错;
10、找到目录platforms\android-16\data\res\values\attrs.xml,参照TextView讲解;
11、在工程里res/values目录下创建attrs.xm文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SettingItemView">
<attr name="title" format="string" />
<attr name="desc_on" format="string" />
<attr name="desc_off" format="string" />
</declare-styleable>
</resources>
12、属性使用,讲解两个参数的构造方法:
在布局文件里面所定义的所有属性,都会被封装到AttributeSet 的属性集合里面;
13、得到属性值(attrs.getAttributeValue(0))并打印出来;
14、使用更方便的方法:
attrs.getAttributeValue("http://schemas.android.com/apk/res/com.itheima.mobilesafe", "title");
15、把得到的值关联到各个控件里去;
16、删除SettingActivity用代码设置的描述信息和标题信息;
17、在布局文件里多次使用自定义控件,并演示;
13_总结自定义组合控件的过程_10
1、声明一个View对象 继承相对布局,或者线性布局 或者其他的ViewGroup。
2、在自定义的View对象里面重写它的构造方法。在构造方法里面就把布局都初始化完毕。
3、根据业务需求 添加一些api方法,扩展自定义的组合控件;
4、希望在布局文件里面 可以自定义一些属性。
5、声明自定义属性的命名空间。
xmlns:itheima="http://schemas.android.com/apk/res/com.itheima.mobilesafe"
6、在res目录下的values目录下创建attrs.xml的文件 声明你写的属性。
<declare-styleable name="SettingItemView">
<attr name="title" format="string" />
<attr name="desc_on" format="string" />
<attr name="desc_off" format="string" />
</declare-styleable>
7、在布局文件中写哪些你自定义的属性。
8、使用这些定义的属性。自定义View对象的构造方法里面 有一个带两个参数的构造方法
布局文件里面定义的属性都放在 AttributeSet attrs
获取那些定义的属性。
知识点
1、项目的代码组织结构
2、PackageManager 获取应用程序的版本号;
3、URL HttpUrlConntion
4、子线程 handler + message
5、Json解析
6、Intent 显示意图
7、Alterdialog
8、两种上下文
9、下载--FinalHttp
10、安装apk
11、应用程序的签名;
12、ListView gridView 数据适配
13、滚动的TextView
14、自定义组合控件 实现关闭自动更新;
-----------------------------------------------------------------------------------------------
代码组织结构
-
根据业务逻辑划分
-
办公软件
- 出差 com.itheima.travel
- 工资 com.itheima.money
- 会议 com.itheima.meeting
-
网盘
- 上传 com.vdisk.upload
- 下载 com.vdisk.download
- 分享 com.vdisk.share
-
-
根据功能模块划分(Android开发推荐此方法)
- Activity com.itheima.mobilesafe.activty
- 后台服务 com.itheima.mobilesafe.service
- 广播接受者 com.itheima.mobilesafe.receiver
- 数据库 com.itheima.mobilesafe.db.dao
- 对象(java bean) com.itheima.mobilesafe.domain/bean
- 自定义控件 com.itheima.mobilesafe.view
- 工具类 com.itheima.mobilesafe.utils
- 业务逻辑 com.itheima.mobilesafe.engine
项目创建
-
minimum SDK 要求最低的安装版本, 安装apk前,系统会判断当前版本是否高于(包含)此版本, 是的话才允许安装
-
maxSdkVersion 要求最高的安装版本(一般不用)
-
Target SDK 目标SDK, 一般设置为开发时使用的手机版本, 这样的话,系统在运行我的apk时,就认为我已经在该做了充分的测试, 系统就不会做过多的兼容性判断, 从而提高运行效率
-
Compile With 编译程序时使用的版本
闪屏页面(Splash)
- 展示logo,公司品牌
- 项目初始化
- 检测版本更新
- 校验程序合法性(比如:判断是否有网络,有的话才运行)
什么是奋斗
奋斗就是,你每天都很辛苦, 但是,你一年一年会越来越轻松 不奋斗就是, 你每天都很轻松, 但是,你一年一年会越来越辛苦
签名冲突
如果两个应用程序, 包名相同, 但是签名不同, 就无法覆盖安装
正式签名
1. 有效期比较长,一般大于25年
2. 需要设置密码
3. 正式发布应用时,必须用正式签名来打包
测试签名(debug.keystore)
1. 有效期是1年,很短
2. 有默认的别名,密码, alias=android, 密码是androiddebugkey
3. 在eclipse中直接运行项目是,系统默认采用此签名文件
如果正式签名丢失了怎么办?
1. 修改包名, 发布, 会发现有两个手机卫士, 用户会比较纠结
2. 请用户先删掉原来的版本,再进行安装, 用户会流失
3. 作为一名有经验的开发人员,请不要犯这种低级错误
常用快捷键
- ctrl + shift + o 导包
- ctrl + shift + t 快速查找某个类
- 先按ctrl + 2 ,再点L, 创建变量并命名
- ctrl + o , 在当前类中,快速查找某个方法
- ctrl + k, 向下查找某个字符串
- ctrl + shift + k, 向上查找某个字符串
- alt + 左方向键 跳转上一个页面
- ctrl + d 删除当前选中的一行
- ctrl + shift + x 将选中的文字全部变成大写,中文不变
- ctrl + shift + y 将选中的文字全部变成小写,中文不变
子类和父类
子类拥有父类的所有方法, 而且可以有更多自己的方法
Activity(token), Context(没有token) 平时,要获取context对象的话, 优先选择Activity, 避免bug出现, 尽量不用getApplicationContext()
minSdkVersion、targetSdkVersion、maxSdkVersion、target API level四个数值到底有什么区别
targetSdkVersion相对复杂一些,如果设置了此属性,那么在程序执行时,如果目标设备的API版本正好等于此数值,他会告诉Android平台:此程序在此版本已经经过充分测,没有问题。不必为此程序开启兼容性检查判断的工作了。也就是说,如果targetSdkVersion与目标设备的API版本相同时,运行效率可能会高一些。但是,这个设置仅仅是一个声明、一个通知,不会有太实质的作用,比如说,使用了targetSdkVersion这个SDK版本中的一个特性,但是这个特性在低版本中是不支持的,那么在低版本的API设备上运行程序时,可能会报错:java.lang.VerifyError。也就是说,此属性不会帮你解决兼容性的测试问题。你至少需要在minSdkVersion这个版本上将程序完整的跑一遍来确定兼容性是没有问题的。
在default.properties中的target是指在编译的时候使用哪个版本的API进行编译。
综上,上面的四个值其实是作用于不同的时期:target API level是在编译的时候起作用,用于指定使用哪个API版本(SDK版本)进行编译。minSdkVersion和maxSdkVersion是在程序安装的时候起作用,用于指定哪些版本的设备可以安装此应用。targetSdkVersion是在程序运行的时候起作用,用于提高指定版本的设备上程序运行体验。这四个数值在程序编译时也没有严格的检查,比如说,你可以将minSdkVersion设置的比maxSdkVersion还大,他会自动忽略掉错误的maxSdkVersion。