360項目-03

day3筆記

手機防盜5個頁面

  • ...

activity的跳轉動畫

參1 進入頁面的動畫  參2 出去頁面的動畫  
overridePendingTransition(R.anim.next_enter, R.anim.next_exit);

> 用xml文件寫動畫
    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="300"
        android:fromXDelta="100%p"
        android:toXDelta="0" >
    </translate>

手勢滑動 ## 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點

  • 1重寫activity的 onTouchEvent方法android

    //activity的觸摸時會執行 @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); }數據庫

  • 2建立手勢識別器,數組

    gestureDetector = new GestureDetector(getApplicationContext(),
            new GestureDetector.SimpleOnGestureListener());
  • 3在onTouchEvent裏調用安全

    把事件交給手勢識別器進行處理
    mGestureDetector.onTouchEvent(event);
  • 4覆寫 SimpleOnGestureListener裏的onFling 加入滑動判斷處理ide

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                        float velocityY) {
                    int x1 = (int) e1.getRawX();
                    int x2 = (int) e2.getRawX();
                    int y1 = (int) e1.getRawY();
                    int y2 = (int) e2.getRawY();
                    if (Math.abs(x1 - x2) < Math.abs(y1 - y2)) {
                        // y軸方向的移動距離大於x軸方向的移動距離 說明 是在豎直方向上滑動 不作處理 返回
                        return false;
                    }
                    if (x2 - x1 > 150) {
                        // 向右滑動距離超過150 跳轉到上一個頁面
                        preAnim();
                        return true;
                    }
    
                    if (x1 - x2 > 150) {
                        // 向 左滑動距離超過150 跳轉到下一個頁面
                        nextAnim();
                        return true;
                    }
    
                    return false;
                };
  • 手勢識別器監聽接口 全部的功能 new OnGestureListener() {oop

    //點擊事件
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    // TODO Auto-generated method stub
                    return false;
                }
                //按下事件
                @Override
                public void onShowPress(MotionEvent e) {
    
                }
    
                //滑動 隨着手指拖動
                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2,
                        float distanceX, float distanceY) {
                    // TODO Auto-generated method stub
                    return false;
                }

// 長按 @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub優化

}

// 滑動 鬆開手指後響應 @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub return false; }動畫

//按下
                @Override
                public boolean onDown(MotionEvent e) {
                    // TODO Auto-generated method stub
                    return false;
                }
            }

getRawX()和getX()區別: ##

若是咱們是重寫的activity的onTouchEvent(MotionEvent event) 那麼event.getX()和 event.getRawX()的值是相同的ui

若是給一個view(好比一個button) 設置setOnTouchListenerthis

xxx.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("onTouch.getRawY()==" + event.getRawY());
            System.out.getRawY()("onTouch.getY()==" + event.getY());
            //這裏的getRawX()和getRawY()的到的座標是相對於整個手機屏幕的左上角
            //這裏的getX()和getY()的到的座標是相對於當前控件(就是xxx)的左上角,座標值不會 超出控件的寬和高
            return true;
        }
    });

抽取父類 ##

防盜保護設置嚮導的5個頁面 抽取出一個父類 提取相同的屬性和方法

綁定手機SIM卡

保存SIM的序列號到 sharedpreference
  • 獲取sim卡序列號

    須要權限   <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    1 獲取手機管理器
    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
    2.獲取sim卡序列號   每一個sim卡都有一個惟一的序列號
    String simN = telephonyManager.getSimSerialNumber();
  • 回顯數據 在oncreate方法根據是否綁定了sim卡設置不一樣的狀態圖片

安全號碼

  • 填寫安全號碼 而且在進下一個頁面的時候 判斷

    //1獲取輸入的安全號碼
    String safeNum = etSafeNum.getText().toString().trim();
    //2判斷安全號碼是否爲空
    if (TextUtils.isEmpty(safeNum)) {
        ToastUtils.show(getApplicationContext(), "必須填寫安全號碼");
        return;
    }
    //3保存安全號碼
    PreferenceUtils.putString(getApplicationContext(),
            Constants.SJFD_SAFENUM, safeNum);
  • 回顯數據

獲取手機聯繫人

不要忘記權限android.permission.READ_CONTACTS

注意獲取的方法自己不是重點 但要知道系統提供數據 須要用到哪一個類來解析 getContentResolver cursor解析要回

  • 不要去記uri的具體值

    聯繫人數據庫位置 /data/data/com.android.providers.contacts.databases下的contacts2.db
    
    //獲取聯繫人
    public static ArrayList<ItemContacts> getAllPhone(Context ctx) {
    ContentResolver cr = ctx.getContentResolver();
    // content://com.androd.contacts/raw_contacts
    
    Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, // 用戶名
            ContactsContract.CommonDataKinds.Phone.NUMBER, // 電話
            ContactsContract.CommonDataKinds.Phone.CONTACT_ID }, // 聯繫人id
            null, null, null);
    ArrayList<ItemContacts> items = new ArrayList<ItemContacts>();
    while (cursor.moveToNext()) {
        String name = cursor.getString(0);
        String phone = cursor.getString(1);
        int contactsId = cursor.getInt(2);
        ItemContacts item = new ItemContacts(name, phone, contactsId);
        items.add(item);
    }
    return items;

    } //獲取聯繫人頭像

    public static Bitmap getContactsPhoto(Context ctx, long contactsId) { ContentResolver cr = ctx.getContentResolver(); //生成uri 這裏用的拼接 Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, contactsId + ""); InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri); Bitmap bitmap = BitmapFactory.decodeStream(is); try { if (is != null) is.close(); } catch (IOException e) { e.printStackTrace(); } return bitmap; }

  • 獲取手機聯繫人是 耗時操做 放在子線程 並增長一個progressbar

    new Thread() {
        public void run() {
            SystemClock.sleep(1500);
            contactsItems = ContactsUtils.getAllPhone(getApplicationContext());
            runOnUiThread(new Runnable() {// 運行在ui線程 在這裏更新ui
                public void run() {
                    pb_contacts.setVisibility(View.INVISIBLE);
                    lvContacts.setAdapter(new ContactsAdapter());
                }
            });
        };
    }.start();
  • 選擇聯繫人電話回傳後 顯示在EditText上 而後設置光標位置 startActivityForesult setResult etPhone.setSelection(safeNum.length());// 設置光標位置

listview優化 ## 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點 重點

看詳細代碼註釋按照步驟來  重點 必須掌握熟練
    GC_CONCURRENT freed 385K, 18% free 2574K/3116K, paused 9ms+1ms, total 13ms
    (385k是釋放的內存大小)  18% free是可用內存佔的比例   2574K(可用內存)/3116K

開機廣播攔截 ##

  • 接收開啓廣播的權限 不加不會報錯 但會接收不到廣播
    <uses-permission android:name="android.permission.RECEIVEBOOTCOMPLETED" />

    <receiver android:name="com.itheima.mobilesafe91.receiver.BootCompleteReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
      </receiver>
  • 接收廣播後 發送報警短信的邏輯 不要忘記權限 <uses-permission android:name="android.permission.SEND_SMS" />

    public class BootReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // 取出是否開啓防盜保護
            boolean isOpne = PreferenceUtils.getBoolean(context, Constants.SJFD_PRO_OPEN,
                    false);
            if (!isOpne) {
                // 沒有開啓防盜保護
                return;
            }
    
            // 1.取出已經保存的sim卡序列號
            String saveNum = PreferenceUtils
                    .getString(context, Constants.SJFD_BIND_SIM, null);
    
            // 2.從新獲取sim卡序列號
            TelephonyManager tm = (TelephonyManager) context
                    .getSystemService(Context.TELEPHONY_SERVICE);
            String simNumNew = tm.getSimSerialNumber();
            // 3.對比序列號是否相同
            if (!TextUtils.equals(saveNum, simNumNew + "4324")) {
                // sim被更換 手機有可能被盜
                // 發送報警短信給安全號碼
                String safeNum = PreferenceUtils.getString(context, Constants.SJFD_SAFENUM,
                        null);
                SmsManager smsManager = SmsManager.getDefault();// 獲取消息管理器
                // 發送短信 權限
                smsManager.sendTextMessage(safeNum, null, "ni de shouji bei daole", null,
                        null);
            }
        }
    
    }
  • 手機防盜設置5完成進入主頁面

    判斷防盜保護是否開啓

    @Override protected boolean toNext() { if (!cbPro.isChecked()) { ToastUtils.show(getApplicationContext(), "要開啓防盜功能,必須勾選"); return false; } // 保存 設置所有完成的狀態 PreferenceUtils .putBoolean(getApplicationContext(), Constants.SJFDSETOVER, true); startActivity(new Intent(this, SjfdActivity.class)); return true; }

  • 點擊複選框時 保存或者取消狀態

    // CheckBox的選中事件
    cbPro.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            // 保存防盜保護的開啓狀態
            PreferenceUtils.putBoolean(getApplicationContext(),
                    Constants.SJFD_HAS_PRO, isChecked);
        }
    });
  • 回顯數據

    boolean isPro = PreferenceUtils.getBoolean(getApplicationContext(),
            Constants.SJFD_HAS_PRO, false);
    cbPro.setChecked(isPro);
  • 手機防盜主頁面 實現界面和數據初始化

短信攔截廣播

  • 權限 <uses-permission android:name="android.permission.RECEIVE_SMS" />

  • 註冊廣播

    <receiver android:name="com.itheima.mobilesafe91.receiver.SmsReceiver" >
        <intent-filter android:priority="1000" >
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
       </receiver>
  • 獲取短信 不要去死記獲取短信的代碼 重點在獲取後的邏輯 如何處理

    使用"pdus" 這個key來提取SMS pdus數組,其中,每一個對象表示一個SMS消息。
        Object[] objs = (Object[]) intent.getExtras().get("pdus");//protocol description unit
        for (Object pdu : objs) {
            // 把每一個pdus字節數組轉爲SmsMessage對象
            SmsMessage sms = SmsMessage.createFromPdu((byte[]) pdu);
            String body = sms.getMessageBody();// 短信內容
            String phone = sms.getOriginatingAddress();// 短信電話
            process(context, body);
        }
    
    
        private void process(Context context, String body) {
            if (TextUtils.equals("#*location*#", body)) {
                // gps數據
                abortBroadcast();// 終止廣播的繼續傳輸
            } else if (TextUtils.equals("#*wipedata*#", body)) {
                // 遠程銷燬數據
                abortBroadcast();
            } else if (TextUtils.equals("#*alarm*#", body)) {
                // 播放報警音樂
                MediaPlayer mp = MediaPlayer.create(context, R.raw.alarm);
                mp.setLooping(true);// 設置循環播放
                mp.setVolume(1.0f, 1.0f);// 設置音量    鈴聲音量和媒體音量不一樣
                mp.start();// 開始播放
                abortBroadcast();
            } else if (TextUtils.equals("#*lockscreen*#", body)) {
                // 遠程鎖屏
                abortBroadcast();
            }
        }
相關文章
相關標籤/搜索