1. 功能:手机防盗--参数设置
核心知识点: 布局 +保存参数(Sp)+特效+手势
1.1. md5密码加密
md5
1.固定长度密文:128bit 8bite=1byte 16byte-->16进制+补0-->32字符的字符串
2.消息摘要验证完整性:消息摘要获取特征值的过程 DNA
3.不可逆。
保存密码查看技巧:不用每次都导出,太麻烦了。
adb :android 的命令调试工具。
ANDROID_SDK_HOME:C:\Users\itheima\Desktop\itheima_softs\sdk_for_android_studio\sdk
path %ANDROID_SDK_HOME%/platform-tools;
操作步骤
C:\Users\itheima>adb shell --进入调试
[email protected]:/ # cd data/data/ --切换目录
[email protected]:/data/data # cd com.itheima.mobilesafe70
[email protected]:/data/data/com.itheima.mobilesafe70 # ls --显示目录内容
cache
lib
shared_prefs
[email protected]:/data/data/com.itheima.mobilesafe70 # cd shared_pref
[email protected]:/data/data/com.itheima.mobilesafe70/shared_prefs #
cat config.xml --打印文件内容到命令行
<?xml version=‘1.0‘ encoding=‘utf-8‘ standalone=‘yes‘ ?>
<map>
<string name="pwd">123</string>
</map>
[email protected]:/data/data/com.itheima.mobilesafe70/shared_prefs #
1.2. 防盗设置界面布局include_style
1.2.1. style:风格
类似html .css重用控件属性的一个技术 。
创建一个名字,在名字上绑定可重用属性,在控件引用@style 名字代表可重用属性。
达到方便开发 简化界面 方便维护
<TextView
style="@style/Setting_Title"
android:text="1.欢迎使用手机防盗"
/>
注意:后面页面的标题只要配一个text为什么?
<!-- 标题的风格 -->
<style name="Setting_Title" >
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">50dp</item>
<item name="android:background">#39941C</item>
<item name="android:gravity">left|center_vertical</item>
<item name="android:paddingLeft">20dp</item>
<item name="android:textSize">20sp</item>
<item name="android:textStyle">bold</item>
</style>
技巧:Ctrl+1快速抽取
1.2.2. include引入布局
<include layout="@layout/view_four_dots" />
以上一行代码就布局完成四个点
1.3. 强大的基类与ViewUtils
ViewUtils:是XUtils里对注解的支持 简化我们的开发代码。
@Override:标注在类,方法,变量上的信息。由注解处理器来处理。
注解处理器不要求掌握,需要掌握每个注解含义。
findViewById |
@ViewInject(R.id.setting) |
初始化 标注在变量上 |
findViewById setOnClickListener |
@OnClick(R.id.setting) |
事件 标注在方法 要求方法格式: public void 方法名(View view) { //... } |
1.3.1. 常见封装方式
Utils:工具类 静态方法为主的类, 一行代码处理一件事。例:HttpUtil
基类:强大的父类。
月薪5K怎么买房?
5K -->3年 =18万(不吃不喝..)
300万 (牛B的老爸支持了。)
结果18万 +282万==>买房!(亮点!)
所有 有个强大的父类(老爸) 多么好的!
public class BaseActivity extends Activity {
private Class<?> preActivity = null;
private Class<?> nextActivity = null;
public void setPreActivity(Class<?> preActivity) {
this.preActivity = preActivity;
}
public void setNextActivity(Class<?> nextActivity) {
this.nextActivity = nextActivity;
}
/**
* 进入下一页
* @param view
*/
public void nextPage(View view) {
if (nextActivity != null) {
startActivity(new Intent(getBaseContext(), nextActivity));
finish();
}
}
/**
* 返回上一页
* @param view
*/
public void prePage(View view) {
if (preActivity != null) {
startActivity(new Intent(getBaseContext(), preActivity));
finish();
}
}
}
1.4. Activity切换动画:移动
1.4.1. 移动动画
Animation
|---AlphaAnimation 透明度变化动画
|--RotateAnimation 旋转动画
|--TransalateAniation 移动动画
|--ScaleAnimation 缩放动画
动画开发注意事项
1.坐标系 坐标原点在左上角
AnimationUtils |
动画文件转动画对象 loadAnimation |
ImageView act = (ImageView) findViewById(R.id.act);
// AnimationUtils:将动画配置文件xml-->动画对象
Animation anim = AnimationUtils.loadAnimation(this, R.anim.one_to_zero);
// 动画
act.startAnimation(anim);
1.4.2. Actvity过渡效果
Activity如何使用上述动画?
overridePendingTransition(int enterAnim 进入动画, int exitAnim 退出动画) |
Pedding即将的意思。在这里是 新打开与刚关闭时的一个过渡动画。 |
下一页 ; 关闭页面移出坐标: 0-》-1 打开页面入坐标 1-》0
上一页 : 打开页面入坐标 -1-》0 关闭页面移出坐标 0-》1
/**
* 进入下一页
*
* @param view
*/
public void nextPage(View view) {
if (nextActivity != null) {
startActivity(new Intent(getBaseContext(), nextActivity));
finish(); 动画之前一定先调finish
// Pending正要发生的
overridePendingTransition(R.anim.one_to_zero, R.anim.zero_to_one_);
}
}
/**
* 返回上一页
* @param view
*/
public void prePage(View view) {
if (preActivity != null) {
startActivity(new Intent(getBaseContext(), preActivity));
finish();
overridePendingTransition(R.anim.one_to_zero_, R.anim.zero_to_one);
}
}
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXDelta="-100%" 倍数
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="0" >
<!-- 原点 到1倍 500 -->
</translate>
1.5. GestrueDetector手势切换
手势:用户对手机的常见操作。
双击。单击。长按。
重写onTouchEvent
GestrueDetector:手势识别器 将用户的操作分析为几个方法来处理。一个方法对应一个手势。
例:onFliling对应滑动。
GestrueDetector |
手势识别器,识别手势的对象 |
SimpleOnGestrueListener |
可以看成一个简单实现。 看作一些常用监听器的集合。 OnClickListener OnLongClickListener |
// 响应用户对界面的操作
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return mGestureDetector.onTouchEvent(event);
}
// 手势识别器:将操作分解方法
private GestureDetector mGestureDetector = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// GestureDetector.OnGestureListener:识别手势调用对应方法
// SimpleOnGestureListener对OnGestureListener实现:常用监听器的集合
// SimpleAdapter-->BaseAdapter
// Button OnClickListener OnLongClickListener
SimpleOnGestureListener listener = new SimpleOnGestureListener() {
//按下
// @Override
// public boolean onDown(MotionEvent e) {
// // TODO Auto-generated method stub
// Toast.makeText(getBaseContext(), "你被按下了 从后面。", 0).show();
// return super.onDown(e);
// }
//
//长按
// @Override
// public void onLongPress(MotionEvent e) {
// // TODO Auto-generated method stub
// super.onLongPress(e);
// Toast.makeText(getBaseContext(), "你被长。。按。", 0).show();
// }
// 滑动
// boolean true 你处理 了这个事件就终止
// false 由系统处理
// velocity速度
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (Math.abs(velocityX) < 200) {
Toast.makeText(getBaseContext(), "你滑得太慢了", 0).show();
return true;
}
// MotionEvent:按下坐标 对象
if (e2.getRawX() - e1.getRawX() > 200) {
prePage(null);
return true;// 处理事件了
}
if (e1.getRawX() - e2.getRawX() > 200) {
nextPage(null);
return true;// 处理事件了
}
return super.onFling(e1, e2, velocityX, velocityY);
}
};
mGestureDetector = new GestureDetector(listener);
}
}
1.6. 绑定sim卡号
Sim卡序列号 :运营商的卡编号
TelephonyManager |
Manager系统级的服务 跟通讯有关的参数都可以通过该服务获取。 get.. 1.sim卡序列号 2.通讯 响铃 接听 挂断 配置权限 READ_PHONE_STATE |
@OnClick(R.id.bind)
public void bindOrUnbind(View view) {
// 08-05 07:41:42.885: I/wzx(1361): Set2Activity --89014103211118510720
if ("未绑定sim卡,请绑定".equals(bind.getText().toString().trim())) {
// 获取服务 注意加权限
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// 获取序列卡号
String sim = tm.getSimSerialNumber();
if (sim == null)// 超级模拟器不付费的话不能获取sim 卡号 模拟 一个
{
sim = "89014103211118510720";
}
Log.i("wzx", "Set2Activity --" + sim);
Editor editor = getSharedPreferences("config", Context.MODE_PRIVATE).edit();
editor.putString("sim_number", sim);
editor.commit();
bind.setText("已绑定,可解除sim卡绑定");
bind.setSelected(true);
} else {
Editor editor = getSharedPreferences("config", Context.MODE_PRIVATE).edit();
editor.putString("sim_number", null);
editor.commit();
bind.setText("未绑定sim卡,请绑定");
bind.setSelected(false);
}
}
1.7. 设置安全号码
1.7.1. 输入保存
在输入过程实时保存参数(sp)
TextWatcher |
输入内容的监听器。 |
//显示保存的安全号码
String safenumberString=getSharedPreferences("config", Context.MODE_PRIVATE).getString("safenumber", "");
safenumber.setText(safenumberString);
// On..Listener
TextWatcher watcher = new TextWatcher() {
// 响应正在输入
// CharSequence:字符序列 --》String
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.i("wzx", "onTextChanged " + s.toString().trim());
Editor editor = getSharedPreferences("config", Context.MODE_PRIVATE).edit();
editor.putString("safenumber", s.toString().trim());
editor.commit();// 生成标签
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
};
//添加输入监听器
safenumber.addTextChangedListener(watcher);
1.7.2. 静态ui联系人选择
① 创建Activity
② 布局ui
③ 循环数据:假数据 --- 难点
④ 创建适配器
⑤ 设置给列表
注意事项:
1.数据是假的。
2.点击 选中的号码设置EditText
@OnClick(R.id.select)
public void select(View view) {
// startActivity(new Intent(this, SelectContactActivity.class));
// startActivityForResult(意图,请求码);
startActivityForResult(new Intent(this, SelectContactActivity.class), 100);
}
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long itemid) {
ContactInfo info=list.get(position);
Log.i("wzx", info.phone);
//设置响应码
Intent intent=new Intent();
intent.putExtra("number", info.phone);
// setResult(响应码,意图 Map 保存处理结果);
setResult(200,intent);
finish();
}
//处理响应
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(100==requestCode&&200==resultCode)
{
String number=data.getStringExtra("number");
Log.i("wzx", "onActivityResult "+number);
safenumber.setText(number);//TextWatcher
}
}
1.7.3. 联系人数据获取
获取ContentProvider数据必须有 1.正确的地址 2.内容解析者
必须添加 READ_CONTACTS权限 隐私
public class ContactUtils {
/**
* 获取联系人数据
*
* @param context
* @return
*/
public static List<ContactInfo> getAllContacts(Context context) {
List<ContactInfo> list = new ArrayList<ContactInfo>();
// 获取解析者
ContentResolver resolver = context.getContentResolver();
// 访问地址
Uri raw_contacts = Uri.parse("content://com.android.contacts/raw_contacts");
Uri data = Uri.parse("content://com.android.contacts/data");
// 查询语句
// select contact_id from raw_contacts;//1 2 3 4
// select mimetype,data1 from view_data where raw_contact_id=3;
// Cursor cursor=resolver.query(访问地址, 返回字段 null代表全部, where 语句, 参数, 排序)
Cursor cursor = resolver.query(raw_contacts, new String[] { "contact_id" }, null, null, null);
while (cursor.moveToNext()) {
// getColumnIndex根据名称查列号
String id = cursor.getString(cursor.getColumnIndex("contact_id"));
// 创建实例
ContactInfo info = new ContactInfo();
info.id = id;
Cursor item = resolver.query(data, new String[] { "mimetype", "data1" }, "raw_contact_id=?", new String[] { id }, null);
while (item.moveToNext()) {
String mimetype = item.getString(item.getColumnIndex("mimetype"));
String data1 = item.getString(item.getColumnIndex("data1"));
if ("vnd.android.cursor.item/name".equals(mimetype)) {
info.name = data1;
} else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
info.phone = data1;
}
}
item.close();
// 添加集合
list.add(info);
}
cursor.close();
return list;
}
}
1.8. 显示所有参数
SharedPreferences sp=getSharedPreferences("config", Context.MODE_PRIVATE);
Editor editor=sp.edit();
editor.putBoolean("finish_set", true);
editor.commit();
//显示安全号码
String safenumberString=sp.getString("safenumber", "");
safenumber.setText(safenumberString);
//显示防盗功能开启
Boolean open_protect=sp.getBoolean("open_protect",false);
protect_open.setSelected(open_protect);