手机卫士涉及的知识点总结

手机卫士涉及的知识点总结

Splash界面

splash: 溅,洒

  • 展现产品的logo提升产品的知名度
  • 初始化操作(创建数据库,读取配置文件)
  • 连接服务器检查软件授权
  • 连接服务器检查软件的更新

自动更新的前提

  • 包名一致
  • 签名一致

状态选择器
整体取消掉标题栏:在清单文件中加一修改主题
Android:theme=”@android:style/Theme.Light.NoTitleBar”
PackageManager:获取各种包的信息(版本、应用程序图标、包信息等)
开源项目框架:
xUtils-2.6.8.jar 断点下载
使用:

HttpUtils httputils=new HttpUtils();
httputils.download(url,target,autoResume,callback);
//url:下载的路径
//targer:存放的路径sd
//autoResume:true是否断点续传
//callback:下载回传
new RequestCallBack(){
    重写onSuccess();
    重写onFailure();
    重写onload();//显示下载进度在textview中当前/总进度
}

开源项目断点下载xUtils耗时操作

        HttpUtils http=new HttpUtils();
        final File file=new File(Environment.getExternalStorageDirectory(),"xxx.apk");
        http.download(data.downLoadUrl, file.getAbsolutePath(), true, new RequestCallBack(){
            //下载失败
            @Override
            public void onFailure(HttpException arg0, String arg1) {

            }
            //下载成功
            @Override
            public void onSuccess(ResponseInfo arg0) {
                //下载成功,替换安装模板代码
                ToastUtils.show(SplashActivity.this, "下载成功");
                Intent intent=new Intent();
                intent.setAction("android.intent.action.VIEW");
                intent.addCategory("android.intent.category.DEFAULT");
                intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                startActivity(intent);

            }});
下载替换安装只要调用系统的应用就行:(模板代码)

Itent intent=new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
startActivity(intent);

市面上常用界面-九宫格

//背景颜色选择



    //按住时
   //聚焦时
   //默认状态




按住图标显示不一样的图片,新建一个tupian.xml文件,引用图标时R.drawable.tupian.xml
//图标状态选择


 
 //按住时 
 //聚焦时 
 //默认状态

走马灯效果按钮

Button可实现,当点击按钮的时候滚动起来设置属性

      android:focusableInTouchMode="true"
      android:ellipsize="marquee"android:text="显示的内容"

TextView也可以实现滚动走马灯:需要自定义TextView,实现里面的所有构造函数并重写isFocused()直接返回true

@Override@ExportedProperty(category = "focus"
  )public boolean isFocused() {
   return true;}
设置一条线可以使用
View自定义组合控件:
textView+checkBox 下面还有一条分割线
public class SettingCheckView extends LinearLayout {public SettingCheckView(Context context, AttributeSet attrs) { 
super(context, attrs);
 initial(context); 
String bigtitle=attrs.getAttributeValue("http://schemas.android.com/apk/res
/com.cca.mobilephone", "bigtitle"); 
tv_title.setText(bigtitle);} 
    public SettingCheckView(Context context) { super(context); 
initial(context);}private void initial(Context context) { 
this.setOrientation(LinearLayout.VERTICAL);// 
this.addView(View.inflate(context, R.layout.ui_setting_view, null));}}

布局文件




使用时:


自定义属性:

先声明属性命名空间

   xmlns:mobilephone="http://schemas.android.com/apk/res/com.cca.mobilephone"

在values定义一个attrs.xml文件,在里面声明功能




    

    //或者
 
    


做到这里就可以使用自定义组合控件了,功能可以设置文本内容,想增加其他的属性,在attrs中定义出来就可以使用了。

自定义对话框:

  AlertDialog.Builder builder=new Builder(context);
    View dialogview=View.inflate(context, R.layout.show_setup_dialog, null);
    builder.setView(view);
    builder.show();

//高低版本默认的背景色和字体颜色不一样、使高低版本保持一致的样式需
设置其背景色、文本字体色

 AlertDialog.Builder builder=new Builder(MainActivity.this);
View dialogview=View.inflate(context, R.layout.show_setup_dialog, null);
AlertDialog dialog=builder.create();
dialog.setView(dialogview,0,0,0,0);//设置对话框上下左右的距离
dialog.show();

show_setup_dialog的xml布局文件如下:



    
    
    
    

        

自定义背景选择器:btn_background.xml(要放在drawable文件下)



    
     
     

    


当有很多个界面有相同的方法,相同的布局时,都要存储数据时,可定义一个父类让其他的类来继承它
动画的切换效果:
//一句代码,必须要放在Activity或者finish()的后面

 overridePendingTransition(R.anim.trans_next_in, R.anim.trans_next_out);

在res目录下建立一个anim文件夹:创建两个xml:trans_next_in.xml和trans_next_out.xml如下









手势识别器

1、先声明一个手势识别器

  private GestureDetector  mGestureDetector;

2、初始化一个手势识别器

//2、初始化手势识别器
    mGestureDetector=new GestureDetector(getApplicationContext(), new GestureDetector.SimpleOnGestureListener(){

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2,
                float velocityX, float velocityY) {
            /**
             * e1、手指触摸屏幕的一瞬间
             * e2、手指离开屏幕的一瞬间
             * velocityX、velocityY:水平方向和竖直方向的速度
             * 
             */
            if((e1.getRawX()-e2.getRawX())>150){
                showNext();
                overridePendingTransition(R.anim.trans_next_in, R.anim.trans_next_out);
                return true;
            }
            if((e2.getRawX()-e1.getRawX())>150){
                showPre();
                overridePendingTransition(R.anim.trans_pre_in, R.anim.trans_pre_out);
                return true;
            }
            return super.onFling(e1, e2, velocityX, velocityY);
        }
    });

3、第三步、使用户识别手势器的动作

//第三步、使用手势识别器识别用户的动作

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    mGestureDetector.onTouchEvent(event);
    return super.onTouchEvent(event);
}

绑定手机卡、获取手机序列号,一个手机号对应一个序列号

   //用到一个系统的服务
private TelephonyManager tm=(TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
//获取手机序列号
String sim=tm.getSimSerialNumber();

电话联系人

data/data/com.android.providers.contacts.database.contacts2.db

对应三张表:
查找联系人工具类:

public class ContactsInfoUtils {

public static List getContactsInfo(Context context){

List infocontacts=new ArrayList();
    //获取内容提供者的解析器
    ContentResolver resolver=context.getContentResolver();
    Uri uri=Uri.parse("content://com.android.contacts/raw_contacts");
    Uri dataUri=Uri.parse("content://com.android.contacts/data");
    //游标
    Cursor cursor=resolver.query(uri, new String[]{"contact_id"}, null, null, null);
    //遍历游标集合
    while(cursor.moveToNext()){
        String id=cursor.getString(0);
        System.out.println("id"+id);
        ContactsInfo infos=new ContactsInfoUtils().new ContactsInfo();
        Cursor datacursor=resolver.query(dataUri, new String[]{"data1"}, "raw_contact_id=?", null, null);
        while(datacursor.moveToNext()){
            String data1=datacursor.getString(0);
            String mimetype=datacursor.getString(1);
            if("vnd.android.cursor.item/name".equals(mimetype)){
                //姓名
                infos.name=data1;
            }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
            //电话
                infos.phone=data1;
            }else if("vnd.android.cursor.item/email_v2".equals(mimetype)){
            //电话
            infos.email=data1;
            }
        }
        infocontacts.add(infos);
    }
    return infocontacts;

}
public class ContactsInfo{
    public String name;
    public String email;
    public String phone;
}
}

密码加密:md5 单向加密,不可逆原文–>密文

public static String encode(String text){

    try {
        MessageDigest digest=MessageDigest.getInstance("md5");
        String password="234";
        byte[] result=digest.digest(password.getBytes());
        StringBuffer sb=new StringBuffer();
        for(byte b:result){
            String hex=Integer.toHexString(b&0xff)+2;//加盐更好更安全
            if(hex.length()==1){
                sb.append("0");
            }
            sb.append(hex);
        }
        return sb.toString();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return "";
    }
}

播放报警音乐:便捷方式:src下新建目录raw可放音乐文件

MediaPlayer mediaplayer=MediaPlayer.create(context, R.raw.uri);
            //循环播放
            mediaplayer.setLooping(true);
            //设置音量最大声
            mediaplayer.setVolume(1.0f, 1.0f);

            mediaplayer.start();
            abortBroadcast();

超级管理员:

Android 2.2引入了支持企业应用程序提供Android设备管理API。设备管理API提供了设备管理功能在系统水平。这些api允许您创建安全性敏感的应用程序是有用的在企业环境中,IT专业人员需要丰富的控制员工的设备。例如,内置Android电子邮件应用程序利用了新的api来改善交流的支持。通过电子邮件应用程序,交流管理员可以执行密码策略——包括字母数字密码或数字针——在设备。管理员也可以远程擦除(即恢复工厂默认值)丢失或被盗的手机。用户可以同步他们的电子邮件和日历数据交换。Email clientSecurity application that to remove wipeDevice management service and application
一键锁屏应用:能够一键锁屏,一键卸载
步骤:
1、先创建admim类继承DeviceAdminReceiver
2、配置清单文件(参考api文档)

 
        
        

        
            
        
    

还要新建一个 res目录下xml文件夹并新建device_admin_sample.xml:
声明中使用的安全策略的元数据提供了特定于设备管理员的附加信息,可通过DeviceAdminInfo类进行解析查看,以下为device_admin_sample.xml:的内容




   






 

3、主活动中书写代码

点击按钮一键锁屏:

  public void lockscreen(View view){
    DevicePolicyManager dpm=(DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
    ComponentName who=new ComponentName(this, Admin.class);
    if(dpm.isAdminActive(who)){
        //重置密码
        //dpm.resetPassword("123", 0);
        //清除sd卡数据
        //dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);

        dpm.lockNow();
        finish();
    }else{
        Toast.makeText(this, "请先激活应用程序", 0).show();
    }

}

使用时:先来到系统设置界面,找到安全、进入设备管理器、找到一键锁屏,点击激活一键锁屏,此时可以使用了。
先激活应用程序
给用户一个很好的体验:来个按钮“先激活应用程序”

Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); 
ComponentName who=new ComponentName(this, Admin.class); 
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, who); 
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"请大家赶紧去激活程序吧,首次激活有大礼包!"); 
startActivity(intent);

一键卸载

再来个卸载按钮:

public void deleteLockScreen(View view){
    DevicePolicyManager dpm=(DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
     ComponentName who=new ComponentName(this, Admin.class);
    dpm.removeActiveAdmin(who);

    Intent intent=new Intent();
    intent.setAction(Intent.ACTION_DELETE);
    intent.setData(Uri.parse("package:"+getPackageName()));
    startActivity(intent);
}
获取位置的经纬度(真实标准坐标)在中国要转换成火星坐标才能真正确定位置
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //获取位置内容提供者
    LocationManager lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);

    Criteria criteria=new Criteria();
    //指定高精度
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    //指定高耗电量
    criteria.setPowerRequirement(Criteria.POWER_HIGH);
    //获取最好的内容提供者
   String provider =lm.getBestProvider(criteria, true);

    lm.requestLocationUpdates(provider, 0, 0, new LocationListener() {
        //状态改变时调用
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {   
        }
        //可用时调用
        @Override
        public void onProviderEnabled(String provider) {
        }   
        @Override
        public void onProviderDisabled(String provider) {

        }       
        @Override
        public void onLocationChanged(Location location) {      
            location.getLatitude();//纬度
            location.getLongitude();//经度
            System.out.println("纬度:"+location.getLatitude()+"------经度:"+location.getLongitude());

            TextView text=new TextView(getApplication());
            text.setTextColor(Color.RED);
            text.setText("纬度:"+location.getLatitude()+"------经度:"+location.getLongitude());

        }
    } );

}
标准坐标—->>中国的火星坐标

使用算法:导入modifyOffset.Java和axisoffset.dat
直接到代码中使用:

ModifyOffset no =ModifyOffset.getInstance(context.getClassLoader().getResourceAsStream("axisoffset.dat"));

//真实坐标X经度 Y为纬度
//不过查找时外国网站经度放在围纬度后面:纬度,经度

PointDouble pt =new PointDouble(x,y);
PointDouble marpoint=mo.s2c(pt);

System.out.println(marpoint.toString());
//输出的是x=。。。。,y=。。。。。经纬度

listView的简单优化

容易内存溢出

1、尽量复用convertview历史的缓存,减少创建新的view对象

2、尽量的减少子孩子的id的查询次数,定义一个viewHolder

View view;
viewHolder holder;
if(convertView!=null){
    //复用历史的view对象
    view=convertView;
    holder=(viewHolder) view.getTag();
}else{
    //创建新的孩子时加上标签
     holder=new viewHolder();
     view=View.inflate(getApplicationContext(), R.layout.item_callsmssafe, null);
     holder.black_phone=(TextView) view.findViewById(R.id.tv_black_phone);
     holder.black_mode=(TextView) view.findViewById(R.id.tv_black_mode);
     view.setTag(holder);

}
//内部类
class viewHolder{
    public TextView black_phone;
    public TextView black_mode;
    public ImageView black_delete;
}
listView显示数据库中的数据时,当listview发生变化时应更新listview数据
 //通知listview更新数据
adapter.notifyDataSetChanged();  
在清单文件中配置广播接收者的特点是:不管应用程序进程是否存在都能接受到对应广播

短信拦截:开启服务并在里面注册一个广播接收者
开启服务:

     Intent intent=new Intent(SettingActivity.this,CallSmsSafeService.class);    
     startService(intent);  

//服务里面代码动态注册一个广播接收者


public class CallSmsSafeService extends Service {
    private BlackNumberDao dao;
    private InnerReceiver receiver;
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        dao=new BlackNumberDao(this);
    //动态注册
        receiver=new InnerReceiver();
        IntentFilter filter=new IntentFilter();
        //设置关心短信到来的动作
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");
        filter.setPriority(Integer.MAX_VALUE);
        //代码注册广播接收者
        registerReceiver(receiver, filter);
        System.out.println("黑名单短信拦截开启了!!!!!");
        super.onCreate();

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
        receiver=null;
    }
    //内部类广播接收者
    private class InnerReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            //拦截短信
            Object[] objs=(Object[]) intent.getExtras().get("pdus");
            for(Object obj:objs){
                SmsMessage smsMessage=SmsMessage.createFromPdu((byte[])obj);
                String address=smsMessage.getOriginatingAddress();
                String result=dao.find(address);
                if("2".equals(result)||"3".equals(result)){
                    System.out.println("黑名单短信拦截模式。。。");
                    abortBroadcast();
                }
                //智能拦截
                String body=smsMessage.getMessageBody();
                if(body.contains("天使")){//分词算法
                    SmsManager.getDefault().sendTextMessage("13531829360", null, "帮你拦截了天使客一条消息", null, null);

                    abortBroadcast();
                }
            }
        }
    }
}
服务断电就会自动停止,用sp存储不会保存状态,读取系统的的运行信息,调用系统的活动和服务管理者ActivityManager可以判断服务是否正在后台运行
/**
 * 判断系统的服务是否在后台运行
 * context:上下文
 * StringName: 服务的全路经名
 */
public static boolean isServiceRunning(Context context,String StringName){

    ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List infos=am.getRunningServices(100);
    for(RunningServiceInfo info:infos){
            String className=info.service.getClassName();
            if(StringName.equals(className)){
                return true;
            }
    }
    return false;
}

利用反射原理挂断电话

    /**
     * 挂断电话的方法,利用反射
     */
    public void endCall() {
        try {
            Class clazz=CallSmsSafeService.class.getClassLoader().loadClass("android.os.ServiceManager");
            Method method=clazz.getDeclaredMethod("getService", String.class);
            IBinder ibinder=(IBinder) method.invoke(null, TELEPHONY_SERVICE);
            ITelephony iTelephony=ITelephony.Stub.asInterface(ibinder);
            iTelephony.endCall();


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

删除通话的记录(内容观察者)

//监视呼叫记录的的数据库,看什么时候生成了,
//就把它删除
Uri uri=Uri.parse("content://call_log/calls");
getContentResolver().registerContentObserver(uri, true,new ContentObserver(new Handler()) {

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        deleteCallLog(incomingNumber);
    }
});


/**
 * 删除拨号记录
 * @param incomingNumber
 */
public void deleteCallLog(String incomingNumber) {

    ContentResolver resolver=getContentResolver();
    Uri uri=Uri.parse("content://call_log/calls");
    resolver.delete(uri, "number=?", new String[]{incomingNumber});
}
打断点、看内存、查源码

电话的拦截功能:

 * 定义电话管理的服务
 */
private TelephonyManager tm;
private MyPhoneStateListener listener;

    /**
     * 实例化电话管理的服务
     */
    tm=(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    //注册电话的监听器
    listener=new MyPhoneStateListener();
    //监听电话的状态的改变
    tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
监听器的注册
class MyPhoneStateListener extends PhoneStateListener{

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        super.onCallStateChanged(state, incomingNumber);

        switch(state){
        case TelephonyManager.CALL_STATE_IDLE://空闲状态
            break;

        case TelephonyManager.CALL_STATE_RINGING://响铃状态

            String mode=dao.find(incomingNumber);
            if(mode.equals("1")||mode.equals("3")){
                System.out.println("挂断电话");

            }

            break;

        case TelephonyManager.CALL_STATE_OFFHOOK://接听状态
            break;

        }
    }

}

ActivityManager:获取进程和服务的管理

ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE) ;    

//获得系统运行的进程  
List appList1 = mActivityManager  
        .getRunningAppProcesses();  
for (RunningAppProcessInfo running : appList1) {  
    System.out.println(running.processName);  
}  
System.out.println("================");  

//获得当前正在运行的service  
List appList2 = mActivityManager  
        .getRunningServices(100);  
for (ActivityManager.RunningServiceInfo running : appList2) {  
    System.out.println(running.service.getClassName());  
}  

System.out.println("================");  

//获得当前正在运行的activity  
List appList3 = mActivityManager  
        .getRunningTasks(1000);  
for (ActivityManager.RunningTaskInfo running : appList3) {  
    System.out.println(running.baseActivity.getClassName());  
}  
System.out.println("================");  

//获得最近运行的应用  
List appList4 = mActivityManager  
        .getRecentTasks(100, 1);  
for (ActivityManager.RecentTaskInfo running : appList4) {  
    System.out.println(running.origActivity.getClassName());  
    }  
判断某个进程或服务是否在后台进行的工具类:
package com.cca.mobilephone.Utils;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
public class ServicerUtils {

/**
 * 判断系统的服务是否在后台运行
 */
public static boolean isServiceRunning(Context context,String StringName){

    ActivityManager am=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List infos=am.getRunningServices(1000);
    for(ActivityManager.RunningServiceInfo info:infos){

            String className=info.service.getClassName();
            System.out.println(className);
            if(StringName.equals(className)){
                System.out.println(className);
                return true;
            }
    }
    return false;
}

}

数据库的增删改查

package com.cca.mobilephone.db.dao;

import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.cca.mobilephone.db.BlackNumberOpenHeloper;
import com.cca.mobilephone.domain.BlackNumberInfo;

public class BlackNumberDao {

private BlackNumberOpenHeloper openhelper;

/**
 * 数据库的构造函数
 * @param context
 */
public BlackNumberDao(Context context) {
    super();
    openhelper=new BlackNumberOpenHeloper(context);
}



/**
 * 往数据库中增加号码
 * @param phone 增加的电话号码
 * @param mode  模式
 * @return
 */
public boolean add(String phone,String mode){
    SQLiteDatabase db=openhelper.getWritableDatabase();     
    ContentValues values=new ContentValues();
    values.put("phone", phone);
    values.put("mode", mode);

    long id=db.insert("blacknumberinfo", null, values);
    db.close();
    if(id!=-1){
        return true;
    }else{
    return false;
    }

}


/**
 * 修改黑名单的拦截模式
 * @param phone 要修改的黑名单号码
 * @param newmode 新的拦截模式
 * @return 修改是否成功
 */
public boolean update(String phone,String newmode){

    SQLiteDatabase db=openhelper.getWritableDatabase();
    ContentValues values=new ContentValues();
    values.put("mode", newmode);
    int rowcount=db.update("blacknumberinfo", values, "phone=?", new String[]{phone});
    db.close();
    if(rowcount==0){
        return false;
    }else{
        return true;
    }
}
/**
 * 查找黑名单号码的拦截模式
 * @param phone 要查找的电话号码
 * @return  返回拦截的模式
 */
public String find(String phone){
    String mode=null;
    SQLiteDatabase db=openhelper.getReadableDatabase();
    Cursor cursor=db.query("blacknumberinfo", null, "phone=?", new String[]{phone},null, null, null);
    if(cursor.moveToNext()){
        mode=cursor.getString(cursor.getColumnIndex("mode"));;
    }
    cursor.close();
    db.close();
    return mode;

}

/**
 * 删除黑名单号码
 * @param phone  要删除的号码
 * @return  是否删除成功
 */

public boolean delete(String phone){
    SQLiteDatabase db=openhelper.getWritableDatabase();
    int rowcount=db.delete("blacknumberinfo", "phone=?", new String[]{phone});
    db.close();
    if(rowcount==0){
        return false;
    }{
        return true;
    }
}
/**
 * 返回全部的黑名单信息
 * @return
 */
public List findAll(){

    SQLiteDatabase db=openhelper.getReadableDatabase();
    Cursor cursor=db.query("blacknumberinfo", null, null, null, null, null, "_id desc");
    List infos=new ArrayList();
    while(cursor.moveToNext()){
        String phone=cursor.getString(cursor.getColumnIndex("phone"));
        String mode=cursor.getString(cursor.getColumnIndex("mode"));
        BlackNumberInfo info=new BlackNumberInfo();
        info.setPhone(phone);
        info.setMode(mode);
        infos.add(info);
    }
    cursor.close();
    db.close();
    return infos;
}

分批加载

/**
 * 分批加载返回的黑名单信息
 * @return
 */
public List findPart(int startIndex,int maxCount){

    SQLiteDatabase db=openhelper.getReadableDatabase();
    Cursor cursor=db.rawQuery("select _id,phone,mode from blacknumberinfo order by _id desc limit ? offset ?", new String[]{
            String.valueOf(maxCount),String.valueOf(startIndex)
    });

    List infos=new ArrayList();
    while(cursor.moveToNext()){
        String phone=cursor.getString(cursor.getColumnIndex("phone"));
        String mode=cursor.getString(cursor.getColumnIndex("mode"));
        BlackNumberInfo info=new BlackNumberInfo();
        info.setPhone(phone);
        info.setMode(mode);
        infos.add(info);
    }
    cursor.close();
    db.close();
    return infos;
}

分页加载解决内存溢出

/**
 * 分页加载返回的黑名单信息
 * @return
 */
public List findPagper(int pagper){
    SQLiteDatabase db=openhelper.getReadableDatabase();
    Cursor cursor=db.rawQuery("select _id,phone,mode from blacknumberinfo order by _id desc limit ? offset ?", new String[]{
            String.valueOf(10),String.valueOf(pagper*10)
    });

    List infos=new ArrayList();
    while(cursor.moveToNext()){
        String phone=cursor.getString(cursor.getColumnIndex("phone"));
        String mode=cursor.getString(cursor.getColumnIndex("mode"));
        BlackNumberInfo info=new BlackNumberInfo();
        info.setPhone(phone);
        info.setMode(mode);
        infos.add(info);
    }
    cursor.close();
    db.close();
    return infos;
}



/**
 * 获取全部总条目
 * @return
 */

public int getTotalCount(){

    SQLiteDatabase db=openhelper.getReadableDatabase();
    Cursor cursor=db.rawQuery("select count(*) from blacknumberinfo ",null);

    cursor.moveToNext();
    int total=cursor.getInt(0);
    cursor.close();
    db.close();
    return total;
}
}

复制资产目录下的文件到android系统下

    /**
 * 拷贝资产目录下的数据库到Android系统下
 */
private void copyDB(final String name) {

    /*
     * 数据库多时可能耗时
     */
    new Thread(){
        public void run() {
            File file=new File(getFilesDir(),name);
            if(file.exists()&&file.length()>0){
            System.out.println("数据库已经加载过,无需在加载!");
            }else{

            try {
                InputStream is=getAssets().open(name);
                FileOutputStream fos=new FileOutputStream(file);
                byte[] buffer=new byte[1024];
                int len=-1;
                while((len=is.read(buffer))!=-1){
                    fos.write(buffer, 0, len);
                }
                is.close();
                fos.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
            }
        };
    }.start();
}

自定义吐司

    /**
 * 自定义吐司
 * @param address
 */
public void showToast(String address) {
    WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    View view = View.inflate(getApplicationContext(), R.layout.item_toast, null);
    //设置背景,字体等自定义属性
    int which=getSharedPreferences("config", 0).getInt("which", 0);
    int bgs[]={R.drawable.btn_gray_normal,R.drawable.btn_green_normal,R.drawable.btn_gray_pressed,R.drawable.call_show_bg,R.drawable.btn_disabled};
    view.setBackgroundResource(bgs[which]);

    TextView tv_address=(TextView) view.findViewById(R.id.tv_address);
    tv_address.setText(address);
//设置参数params
    WindowManager.LayoutParams params = new WindowManager.LayoutParams();
     params.height = WindowManager.LayoutParams.WRAP_CONTENT;
     params.width = WindowManager.LayoutParams.WRAP_CONTENT;
     params.format = PixelFormat.TRANSLUCENT;
     params.type = WindowManager.LayoutParams.TYPE_TOAST;
     params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
             | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
             | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
    wm.addView(view, params);

}

及时退出吐司的显示用:wm.removeView(view);

控件的拖拽效果
ImageView imgview= (ImageView) findViewById(R.id.imageview);
imgview.setOnTouchListener(new OnTouchListener() {
        int startx;
        int starty;
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            switch(event.getAction()){
            case MotionEvent.ACTION_DOWN://手指第一次触摸控件时调用
                //获取控件在屏幕上的坐标
                startx=(int) event.getRawX();
                starty=(int) event.getRawY();
                break;

            case MotionEvent.ACTION_MOVE://手指在控件上移动的事件
                //手指移动后的偏移量
                int newx=(int) event.getRawX();
                int newy=(int) event.getRawY();
                int dx=newx-startx;
                int dy=newy-starty;
                //移动后的控件新坐标
                imgview.layout(imgview.getLeft()+dx, imgview.getTop()+dy, 
                                imgview.getRight()+dx, imgview.getBottom()+dy);
                //移动后重新初始化控件坐标
                startx=(int) event.getRawX();
                starty=(int) event.getRawY();
                System.out.println("移动了控件"+startx+"---"+starty);
                break;

            case MotionEvent.ACTION_UP://手指离开控件的一瞬间

                break;
            }
            return true;


        }
    });
简单双击效果实现
btn=(Button) findViewById(R.id.btn);
    btn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            if(firsttime>0){
                secondtime=System.currentTimeMillis();
                if((secondtime-firsttime)<500){
                    Toast.makeText(getApplicationContext(), "双击了", 0).show();
                    firsttime=0;
                }else{
                    firsttime=0;
                }
                return ;
            }
            firsttime=System.currentTimeMillis();
            new Thread(){
                public void run() {
                    try {
                        Thread.sleep(500);
                        firsttime=0;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                };
            }.start();
        }
    });
多次点击事件实现
//定义了多长的数组就是多次点击,3就是连续3击    
private long[] mHits=new long[3];
/**
*四个参数:源数组,从第几个开始拷贝,目标数组,从第几个开始拷贝,拷贝的长度
*
*/
System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
mHits[mHits.length-1] = SystemClock.uptimeMillis();
if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {

    Toast.makeText(getApplicationContext(), "多次击了", 0).show();
}
自定义吐司加上拖拽的效果图显示
    /**
 * 自定义吐司
 * @param address
 */
public void showToast(String address) {
    wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    view = View.inflate(getApplicationContext(), R.layout.item_toast, null);

    view.setOnTouchListener(new OnTouchListener() {
        int startx ;
        int starty ;

        @SuppressWarnings("deprecation")
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            switch(event.getAction()){
            case MotionEvent.ACTION_DOWN://手指触摸
                //获取自定义吐司坐标
                startx=(int) event.getRawX();
                starty=(int) event.getRawY();

                break;
            case MotionEvent.ACTION_UP://手指离开
                //存储控件的位置坐标
                 SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
                Editor edit=sp.edit();
                edit.putInt("lastx", params.x);
                edit.putInt("lasty", params.y);
                edit.commit();

                break;
            case MotionEvent.ACTION_MOVE://手指移动
                //获取偏移量
                int newx=(int) event.getRawX();
                int newy=(int) event.getRawY();
                int dx=newx-startx;
                int dy=newy-starty;
                params.x +=dx;
                params.y +=dy;
                //判断view控件是否移出屏幕范围
                if(params.x>(wm.getDefaultDisplay().getWidth()-view.getWidth())){
                    params.x=wm.getDefaultDisplay().getWidth()-view.getWidth();
                }
                if(params.y>(wm.getDefaultDisplay().getHeight()-view.getHeight())){
                    params.x=wm.getDefaultDisplay().getHeight()-view.getHeight();
                }

                wm.updateViewLayout(view, params);
                //重新初始化控件坐标
                startx=(int) event.getRawX();
                starty=(int) event.getRawY();
                break;
            }

            return true;
        }
    });
    //设置背景颜色
    int which=getSharedPreferences("config", 0).getInt("which", 0);
    int bgs[]={R.drawable.btn_gray_normal,R.drawable.btn_green_normal,R.drawable.btn_gray_pressed,R.drawable.call_show_bg,R.drawable.btn_disabled};
    view.setBackgroundResource(bgs[which]);

    TextView tv_address=(TextView) view.findViewById(R.id.tv_address);
    tv_address.setText(address);
    params = new WindowManager.LayoutParams();
     params.height = WindowManager.LayoutParams.WRAP_CONTENT;
     params.width = WindowManager.LayoutParams.WRAP_CONTENT;
     params.format = PixelFormat.TRANSLUCENT;

     //左上对齐
     params.gravity=Gravity.LEFT+Gravity.TOP;
     SharedPreferences sp=getSharedPreferences("config", MODE_PRIVATE);
     params.x=sp.getInt("lastx", 0);
     params.y=sp.getInt("lasty", 0);
     params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
     params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
             | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

    wm.addView(view, params);

}

未完待续。。。

  • 未完待续(适配器)

你可能感兴趣的:(手机卫士涉及的知识点总结)