A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小鲁哥哥 于 2016-12-29 19:49 编辑

【济南中心】Android课程同步笔记day04:Android应用之安全卫士

ListView的Adapter优化
在使用ListView 控件的过程中,由于加载条目过多在滑动时可能造成卡顿。这是因为ListView 在当前屏幕显示多少个条目,就会创建多少个对象,每一个条目都是一个对象。在滑动时,滑出屏幕的条目对象会被销毁,新加载到屏幕上的条目会创建新的对象,这样在ListView 快速滑动时就会不断的【创建对象】->【销毁对象】->【创建对象】,并且每一个条目都需要加载一次布局,加载布局时会不断进行findViewById()操作初始化控件,而布局xml 文件是以树形进行加载,每次加载一个条目都需要从根节点进行初始化,这样对内存消耗也比较大,并且浪费时间。如果每个条目都有图片,图片加载的时间比较长,就会造成内存
溢出异常。为此就需要对ListView 进行优化,优化的目的是在滑动时不会重复创建对象,减少内存消耗和屏幕渲染处理。具体步骤如下:
1.创建一个静态类,将需要加载的控件变量放在该静态类中:
   static class ViewHolder{

   }
2. 复用缓存View 对象
在Adapter 的getView(int position, View convertView, ViewGroup parent)方法中,第二个参数convertView代表的就是之前滑动出屏幕的条目对象。如果是第一次加载该方法时,会创建新的View 对象,如果滑动ListView 时,滑动出屏幕的View 对象会以缓存的形式存在,而convertView就是缓存的View 对象,我们可以复用缓存该对象减少新对象的创建。在加载布局时先判断convertView 是否存在, 如果convertView==null 说明没有缓存的View 对象,则使用View.inflate()方法加载布局,进行布局的初始化,否则复用缓存的View 对象,具体代码如下所示:
[Java] 纯文本查看 复制代码
               @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                        ViewHolder holder;
                        if(null == convertView){
                                //没有可以复用的对象
                                convertView = View.inflate(ContactSelectActivity.this,
                                                R.layout.item_contact, null);
                                holder = new ViewHolder();
                                holder.ivIcon = (ImageView) convertView
                                                .findViewById(R.id.item_contact_iv_icon);
                                holder.tvName = (TextView) convertView
                                                .findViewById(R.id.item_contact_tv_name);
                                holder.tvNumber = (TextView) convertView
                                                .findViewById(R.id.item_contact_tv_number);
                                convertView.setTag(holder);
                        }else{
                                holder = (ViewHolder) convertView.getTag();
                        }
                        ContactBean contactBean = mDatas.get(position);
                        holder.tvName.setText(contactBean.name);
                        holder.tvNumber.setText(contactBean.number);
                        holder.ivIcon.setImageBitmap
                        (ContactProvider.getContactPhoto(ContactSelectActivity.this, contactBean.contactId));
                        return convertView;
                }
手机重启广播
当手机电池拿掉取出sim 卡后插入电池重启时,手机会发出重启手机的广播,定义一个全局侦听器来监听这个广播,然后我们可以进行一定的手机防护功能。首先,定义广播接收者我们需要在清单文件中配置,配置信息如下所示。
[Java] 纯文本查看 复制代码
   <receiver android:name="com.itheima.zphuanlove.receiver.BootCompletedReceiver" >
            <intent-filter android:priority="1000" >
                <!-- 重启手机 -->
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

手机重启需要加一个权限<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED" />创建手机重启的广播接收者BootCompletedReceiver 继承BroadcastReceiver,代码中我们需要获取用户是否绑定sim 卡信息,具体的代码如下所示
[Java] 纯文本查看 复制代码
public class BootCompletedReceiver extends BroadcastReceiver {

        private static final String TAG = "BootCompletedReceiver";

        @Override
        public void onReceive(Context context, Intent intent) {
                Log.d(TAG, "手机重启了....");
                // 1. 判断是否开启防盗保护
                boolean protecting = PreferenceUtils.getBoolean(context,
                                Config.KEY_SJFD_PROTECTING);
                if (!protecting) {
                        // 没有开启防盗保护
                        Log.d(TAG, "没有开启防盗保护....");
                        return;
                }
                Log.d(TAG, "开启了防盗保护....");
                // 2. 比对sim卡
                // 1) 存储的sim
                String sim = PreferenceUtils.getString(context, Config.KEY_SJFD_SIM);
                // 2) 当前手机的sim
                TelephonyManager tm = (TelephonyManager) context
                                .getSystemService(Context.TELEPHONY_SERVICE);
                String currenSim = tm.getSimSerialNumber() + "xxx";// 模拟丢失

                if (sim.equals(currenSim)) {
                        // 存储的和当前的是一致的,手机没有丢失
                        Log.d(TAG, "手机没有丢失....");
                        return;
                }
                // 手机丢失了
                Log.d(TAG, "手机丢失了....");
                // 3. 给安全号码发送报警短信
                Log.d(TAG, "发送报警短信....");
                String number = PreferenceUtils.getString(context,
                                Config.KEY_SJFD_NUMBER);
                SmsManager smsManager = SmsManager.getDefault();
                smsManager.sendTextMessage(number, null, "mobile is lost!!!sos", null,
                                null);
        }
}

当设置了这个广播之后,首先获取用户之前绑定的sim 卡信息,其次获取当前手机中的sim 信息,当二者不一致时,手机重启后就会向用户设置的安全号码中发送报警短信。实现该功能还需要加入一些权限,如下所示
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS" />

短信接收广播之指令分析
定义一个广播SmsReceiver。首先,需要在清单文件中配置信息,priority=1000这是为了保证当前广播具有最高优先权接收信息
[Java] 纯文本查看 复制代码
<receiver android:name="com.itheima.zphuanlove.receiver.SmsReceiver" >
            <intent-filter android:priority="1000" >
                <!-- 接收短信的 -->
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
</receiver>
[Java] 纯文本查看 复制代码
接收GPS 跟踪、发送报警音乐等功能的代码如下所示。
public class SmsReceiver extends BroadcastReceiver {
        private static final String TAG = "SmsReceiver";
        @Override
        public void onReceive(Context context, Intent intent) {
                // 接收短信
                Object[] objs = (Object[]) intent.getExtras().get("pdus");
                for (Object obj : objs) {
                        SmsMessage sms = SmsMessage.createFromPdu((byte[]) obj);
                        // 发送者
                        String sender = sms.getOriginatingAddress();
                        // 发送的内容
                        String content = sms.getMessageBody();
                        String number = PreferenceUtils.getString(context,
                                        Config.KEY_SJFD_NUMBER);
                        // 判断发送者是否是安全号码
                        if (sender.equals(number)) {
                                // 安全号码发送的
                                // 判断内容,是否是指令
                                if ("#*location*#".equals(content)) {
                                        // TODO:
                                        Log.d(TAG, "GPS追踪");
                                } else if ("#*wipedata*#".equals(content)) {
                                        // TODO:
                                        Log.d(TAG, "远程消除数据");
                                } else if ("#*alarm*#".equals(content)) {
                                        // TODO:
                                        Log.d(TAG, "播放报警音乐");
                                } else if (!"#*lockscreen*#".equals(content)
                                                && content.startsWith("#*lockscreen*#")) {
                                        Log.d(TAG, "远程锁屏");
                                } else if ("#*lockscreen*#".equals(content)) {
                                        Log.d(TAG, "远程锁屏");
                                }
                                // 不让用户看到短信内容
                                abortBroadcast();
                        }
                }
        }
}
播放报警音乐
在res下创建一个raw文件夹用于放资源文件alram.mp3. 当发送一个特殊指令之后,无论手机是否处于静音状态,丢失的手机会立即播放这个报警音乐。具体的代码在短信接收广播中进行修改,如下所示
[Java] 纯文本查看 复制代码
if ("#*alarm*#".equals(content)) {
                                        MediaPlayer player = MediaPlayer.create(context,
                                                        R.raw.alarm);
                                        player.setLooping(true);// 无限播放
                                        player.setVolume(1f, 1f);// 设置声音
                                        player.start();
                                        Log.d(TAG, "播放报警音乐");
                                }

手机定位
GPS 跟踪是通过启动一个位置服务GPSService.java 实现的,GPSService的代码如下

[Java] 纯文本查看 复制代码
public class GPSService extends Service {
        private LocationManager mLocationManager;
        private GPSListener mListener;
        @Override
        public IBinder onBind(Intent intent) {
                // TODO Auto-generated method stub
                return null;
        }
       @Override
        public void onCreate() {
                super.onCreate();
                // 获得手机的经纬度
                // 1.获得位置管理者
                mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                // 2. 注册位置监听
                mListener = new GPSListener();
                mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                                0, 0, mListener);
        }
        @Override
        public void onDestroy() {
                super.onDestroy();
                // 4. 注销位置监听
                mLocationManager.removeUpdates(mListener);
                // 5. 注册权限
        }

        // 3. 实现listener
        private class GPSListener implements LocationListener {

                @Override
                public void onLocationChanged(Location location) {
                        double latitude = location.getLatitude();// 纬度
                        double longitude = location.getLongitude();// 经度

                        // 拿到纬度和精度
                        // 1. 转换为经度
                        double[] result = GPSUtils.parse(GPSService.this, latitude,
                                        longitude);
                        // 2. 将转换后的经纬度发送给安全号码
                        SmsManager smsManager = SmsManager.getDefault();
                        String number = PreferenceUtils.getString(GPSService.this,
                                        Config.KEY_SJFD_NUMBER);
                        String text = "longitude:" + result[0] + "  latitude:" + result[1];
                        smsManager.sendTextMessage(number, null, text, null, null);

                        // 3. 停止服务
                        stopSelf();
                }
                @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
                }
        }
}

解析到对应的指令后:
[Java] 纯文本查看 复制代码
if ("#*location*#".equals(content)) {
                                        Log.d(TAG, "GPS追踪");
                                        Intent service = new Intent(context, GPSService.class);
                                        context.startService(service);
                                }
注意在清单文件中注册service,以及添加定位的权限:
<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION" />

手机设备管理员
应用具备手机设备管理员的权限才能清除手机中的数据、锁屏及修改密码的操作首先在清单文件中,需要这样的一段代码
[XML] 纯文本查看 复制代码
<!-- 设备管理员 -->
        <receiver
            android:name=".receiver.SjfdAdminReceiver"
            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>

手机设备管理员是一个广播接受者继承了DeviceAdminReceiver 具体的代码如下
[Java] 纯文本查看 复制代码
public class SjfdAdminReceiver extends DeviceAdminReceiver {
}
device_admin_sample 文件是在res 目录创建的xml 文件夹下的一个xml 文件,具体的代码如下
[XML] 纯文本查看 复制代码
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
    <uses-policies>
        <!-- 重置密码 -->
        <reset-password />
        <!-- 锁屏 -->
        <force-lock />
        <!-- 擦除数据 -->
        <wipe-data />
    </uses-policies>
</device-admin>

1 个回复

倒序浏览
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马