##Day04##
#4.1界面优化处理# ***
1.将加载的操作放到子线程中执行
new Thread(){
public void run() {
//获取联系人
list = ContactsEngine.getAllContacts(getApplicationContext());
handler.sendEmptyMessage(0);
};
}.start();
2.使用进度条显示正在加载
<!-- FrameLayout : 帧布局,会用在视频播放器
在布局文件中最下面的控件,在显示的时候是在最上边
-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/lv_contact_contacts"
android:layout_width="match_parent"
android:layout_height="match_parent"
></ListView>
<!-- layout_gravity : 表示控件在父窗体的位置 -->
<ProgressBar
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</FrameLayout>
在代码中使用
a.注解初始化,声明
//通过注解的方式初始化控件,spring框架其实通过注解获取bean对象
@ViewInject(R.id.loading)
private ProgressBar loading;
在oncreate方法中
//注解初始化控件,其实就相当于通过反射实现findviewbyid的形式
ViewUtils.inject(this);
b.在线程之前显示,在显示数据之后隐藏
loading.setVisibility(View.VISIBLE);显示
loading.setVisibility(View.INVISIBLE);//显示数据隐藏进度条
#4.2异步加载框架# ******
模板设计模式:父类中创建一些方法,但是不知道方法具体的执行代码,交给子类,让子类根据自己的特性去执行相应的代码
原理:源码
其实他内部就是用了子线程来实现了,封装了在子线程之前执行的方法onPreExecute,在子线程之中执行的方法doInBackground,在子线程之后执行的方法onPostExecute,通过在execute方法中调用onPreExecute,然后在创建子线程来执行我们要实现耗时操作,其实就是在子线程中调用doInBackground,doInBackground实现耗时操作,最后通过给handler发送一个消息,然后到handler中去执行onPostExecute
1.写法:
public abstract class MyAsyncTask {
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
postTask();
};
};
/**
* 在子线程之前执行的方法
*/
public abstract void preTask();
/**
* 在子线程之中执行的方法
*/
public abstract void doinBack();
/**
* 在子线程之后执行的方法
*/
public abstract void postTask();
/**
* 执行
*/
public void execute(){
preTask();
new Thread(){
public void run() {
doinBack();
handler.sendEmptyMessage(0);
};
}.start();
}
}
2.调用
//异步加载框架
new MyAsyncTask() {
@Override
public void preTask() {
//在子线程之前执行
loading.setVisibility(View.VISIBLE);
}
@Override
public void postTask() {
//在子线程之后执行
//msg的默认标示what就是0
lv_contact_contacts.setAdapter(new Myadapter());
loading.setVisibility(View.INVISIBLE);//显示数据,隐藏进度条
}
@Override
public void doinBack() {
//在子线程之中执行
//获取联系人
list = ContactsEngine.getAllContacts(getApplicationContext());
}
}.execute();
#4.3修改进度条样式# **
android:indeterminateOnly : 有没有进度条 true:没有 false:有
1.查看 sdk\platforms\android-16\data\res\values\styles.xml
2.res -> drawable -> xxxxx.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/shenmabg"
android:pivotX="50%"
android:pivotY="50%"
/>
3.在控件中使用相应的属性,覆盖系统样式文件中的属性
android:indeterminateDrawable="@drawable/progressbar_drawable"
#4.4设置向导界面流程# ***
1.对setup4Activity进行功能实现
//2.根据保存的防盗保护状态进行回显操作
if (sp.getBoolean(“protected”, false)) {
cb_setup4_protected.setText(“您已经开启了防盗保护”);
cb_setup4_protected.setChecked(true);//实际设置checkbox状态
}else{
cb_setup4_protected.setText(“您还没有开启了防盗保护”);
cb_setup4_protected.setChecked(false);
}
//当checkbox状态发生改变的时候调用
cb_setup4_protected.setOnCheckedChangeListener(new OnCheckedChangeListener() {
//buttonView : checkbox
//isChecked : 已经改变的状态,点击后的状态
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//1.保存防盗保护状态
Editor edit = sp.edit();
//根据状态进行相应的设置
if (isChecked) {
//开启防盗保护
//设置checkbox的文本
cb_setup4_protected.setText("您已经开启了防盗保护");
cb_setup4_protected.setChecked(true);//程序的严谨性
edit.putBoolean("protected", true);
}else{
//关闭防盗保护
//设置checkbox的文本
cb_setup4_protected.setText("您还没有开启了防盗保护");
cb_setup4_protected.setChecked(false);
edit.putBoolean("protected", false);
}
edit.commit();
}
});
2.根据保存的安全号码和防盗保护状态设置相应显示操作,在lostfindActivity中的oncreate的else中
//根据保存的安全号码和防盗保护状态设置相应显示操作
TextView tv_lostfind_safenum = (TextView) findViewById(R.id.tv_lostfind_safenum);
//根据保存的安全号设置安全号码
tv_lostfind_safenum.setText(sp.getString("safenum", ""));
ImageView tv_lostfind_islock = (ImageView) findViewById(R.id.tv_lostfind_islock);
//1.获取保存的防盗保护是否开启状态
boolean b = sp.getBoolean("protected", false);
//2.根据获取的状态设置相应的图片
if (b) {
tv_lostfind_islock.setImageResource(R.drawable.lock);
}else{
tv_lostfind_islock.setImageResource(R.drawable.unlock);
}
3.在BootCompletedReceiver根据保存的防盗保护是否开启状态进行判断操作
//根据保存的防盗保护是否开启状态,来判断是否发送报警短信
if (sp.getBoolean("protected", false)) {
同时修改收件人为保存的安全号码
smsManager.sendTextMessage(sp.getString("safenum", "5556"), null, "da ge wo bei dao le,help me!!!", null, null);
#4.5接受短信# ***
指令发送形式
1.服务器发送,客户端接收,消息推送,通知栏形式来展示,心跳连接(每隔半个小时给服务器发送一个空包)/长连接(在后台一直发送消息,比较耗电,耗流量),第三方sdk,极光推送、百度推送,局限性:必须联网
2.通过短信的方式接受指令,接受解析短信来实现相应的操作
1.创建一个广播接受者,清单文件配置
2.在onreceive方法中接受解析短信
@Override
public void onReceive(Context context, Intent intent) {
//接受解析短信
//接收短信
//70个汉字一条短信,比如71汉字,两条短信
Object[] objs = (Object[]) intent.getExtras().get(“pdus”);
for(Object obj:objs){
//将短信转化成一个SmsMessage
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj);
String body = smsMessage.getMessageBody();//获取短信的内容
String sender = smsMessage.getOriginatingAddress();//获取发件人
System.out.println(“发件人:”+sender+" 短信内容:"+body);
abortBroadcast();//拦截短信,android原生系统中可以实现,但是在国产的深度定制系统中可能不太好使,小米
}
}
#4.6定位方式# **
1.wifi定位,ip地址定位,
2.基站定位,基站:服务电话的设备,信号的强弱就决定了手机距离基站的远近
基站定位和wifi定位局限性:不能定位海拔
3.gps定位,手机和gps定位卫星进行通讯,光波通讯,在室内或者地下室没有办法定位,时间比较长,1分钟,比较费电,不要联网,agps技术,通过网络服务gps进行定位,修正定位坐标,准确度比较准确
百度定位sdk,百度地图sdk,
#4.7定位的具体代码# ***
android.permission.ACCESS_MOCK_LOCATION : 模拟位置的权限,模拟器是必须加的,真机可以不加
android.permission.ACCESS_FINE_LOCATION : 精确位置的权限,真机必须加的
android.permission.ACCESS_COARSE_LOCATION : 大概位置的权限,真机必须加的
passive : 基站定位
gps:gps定位
模拟器不支持wifi定位
定位的具体代码实现
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_main_location = (TextView) findViewById(R.id.tv_main_location);
//1.获取位置的管理者
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
//2.获取定位方式
//2.1获取所有的定位方式,true:返回可用的定位方式
List<String> providers = locationManager.getProviders(true);
for (String string : providers) {
System.out.println(string);
}
//2.2获取最佳的定位方式
Criteria criteria = new Criteria();
//设置可以定位海拔,true:表示可以定位海拔
criteria.setAltitudeRequired(true);//只有gps可以定位海拔
//criteria : 设置定位属性
//enabledOnly : 如果定位可以就返回
String bestProvider = locationManager.getBestProvider(criteria, true);
System.out.println("最佳的定位方式:"+bestProvider);
//3.定位
//provider : 定位方式
//minTime :定位的最小时间间隔
//minDistance : 最小的定位距离
//listener : LocationListener监听
locationManager.requestLocationUpdates(bestProvider, 0, 0, new MyLocationListener());
}
//4.创建一个定位的监听
private class MyLocationListener implements LocationListener{
//定位位置发生变化的时候调用
//location : 当前的位置
@Override
public void onLocationChanged(Location location) {
//5.获取经纬度
location.getAccuracy();//获取精确的位置
location.getAltitude();//获取海拔
double latitude = location.getLatitude();//获取纬度,平行
double longitude = location.getLongitude();//获取经度
tv_main_location.setText("longitude:"+longitude+" latitude:"+latitude);
}
//定位状态发生变化的时候调用
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
//定位可用的时候调用
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
//定位不可用的时候调用
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
}
经纬度
108.85661205
34.19107395
地图在输入坐标的时候,将坐标转化为火星坐标
#4.8.gps定位操作移植到手机卫士# ***
//GPS追踪
System.out.println("GPS追踪");
//定位操作,服务
//1.开启服务
Intent service_intent = new Intent(context,GPSService.class);
context.startService(service_intent);
//2.发送定位坐标
//2.1获取保存的经纬度坐标
String longitude = sp.getString("longitude", "");
String latitude = sp.getString("latitude", "");
//2.2发送坐标
if (!TextUtils.isEmpty(longitude) && !TextUtils.isEmpty(latitude)) {
SmsManager smsManager = SmsManager.getDefault();//短信的管理者
smsManager.sendTextMessage(sp.getString("safenum", "5556"), null, "longitude:"+longitude+" latitude:"+latitude, null, null);
}
abortBroadcast();
#4.9播放报警音乐# ***
1.播放报警音乐之前把系统音量调整到最大
//在播放之前,将系统的音量调整到最大
//1.获取音量的管理者
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
//设置系统的音量
//streamType : 音量的类型
//index : 音量的大小 0最小 15最大
//flags : 指定的信息
//getStreamMaxVolume : 获取最大音量 streamType : 音量的类型
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
2.播放报警音乐
1.在成员变量区域,将MediaPlayer设置成静态的
private static MediaPlayer mediaPlayer;//把mediaplayer放到静态内存中
2.播放报警音乐
//播放报警音乐
if (mediaPlayer != null) {
mediaPlayer.release();//释放资源
}
mediaPlayer = MediaPlayer.create(context, R.raw.ylzs);
//播放音乐
mediaPlayer.start();
#4.10.超级管理员权限# ***
超级管理员权限与root权限区别
root权限:是linux的最高权限,android都是以liunx为内核进行开发的,所以root权限也是android的最高权限,使用root就可以想删什么就删什么,
超级管理员权限:可以做一些比较危险的操作,比如锁屏、删除数据操作,root也可以做,但是root能做的事情超级管理员不一定能做
获取超级管理员权限之后,应用不能卸载
1.获取超级管理员,创建一个广播接受者
public class Admin extends DeviceAdminReceiver {
2.清单文件配置
<receiver
android:name="com.example.yijiansuoping.Admin"
android:description="@string/sample_device_admin_description"
android:label="@string/sample_device_admin"
android:permission="android.permission.BIND_DEVICE_ADMIN" >
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_sample" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
3.res -> xml -> device_admin_sample.xml
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
<expire-password />
<encrypted-storage />
<disable-camera />
</uses-policies>
</device-admin>
4.使用
public class MainActivity extends Activity {
private DevicePolicyManager devicePolicyManager;
private ComponentName componentName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.获取设备的管理者
devicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
//获取admin的组件标示
//cls : 组件的class文件
componentName = new ComponentName(this, Admin.class);
//isAdminActive : 判断超级管理员是否激活
// if (devicePolicyManager.isAdminActive(componentName)) {
// devicePolicyManager.lockNow();//锁屏
// finish();
// }
}
public void locknow(View v){
devicePolicyManager.lockNow();//锁屏
}
//通过代码激活超级管理员
public void ditivate(View v){
//激活超级管理员
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
//设置激活那个超级管理员
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
//设置描述信息
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"一键锁屏,非常好用");
startActivity(intent);
}
//注销超级管理员
public void delete(View v){
if (devicePolicyManager.isAdminActive(componentName)) {
devicePolicyManager.removeActiveAdmin(componentName);//注销超级管理员
}
}
}