Intent&Context&Manager&Listener

Intent&Context&Listener&Manager

  1. Intent數據類型
  2. Context區別
  3. Listener
  4. Manager

01.Intent攜帶的數據類型

  1. 8種基本數據類型以及數組形式以及String
  2. 實現了序列化接口的對象
    1. Serializable(Sun),聲明爲transient 的變量不會被序列化
    2. Parcelable(Google)

public class User implements Parcelable {
  private String name;
  private int age;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  /*
   * 必須聲明:public static final Parcelable.Creator<User> CREATOR反序列化的
   */
  public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
    /*
     * 用於反序列,給你一個數據包,你把數據包中的數據拿出來,封裝成一個對象,並返回
     */
    public User createFromParcel(Parcel in) {
      User user = new User();
      /*
       * 注意:一定按照序列化時的順序讀取
       */
      String name = in.readString();
      int age = in.readInt();
      user.setAge(age);
      user.setName(name);
      return user;
    }
    /*
     * 如果一個對象可以被序列化,那麼這個對象的數組也能被序列化
     */
    public User[] newArray(int size) {
      return new User[size];
    }
  };
  // 用於序列化對象的,將需要序列化出去的屬性寫到數據包中即可
  @Override
  public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeInt(age);
  }
  @Override
  public int describeContents() {
    return 0;
  }
}

3. 前者序列化對象時會產生大量的臨時文件,效率比較低後者效率高

02.Context的區別

  1. Activity 一個Activity對應一個Context
  2. Service 一個Service對應一個Context
  3. BroadCastReceiver中的onReceive(Context)方法執行完了了,這裏的Context就完了
  4. 在內容提供者中獲得上下文getContext()
  5. getApplicationContext()全局上下文
  6. 在fragment中可以通過getActivity()獲得

Context

03.Listener

1. setOnItemClickListener()
2. button.setOnClickListener(OnClickListener);
3. button.setOnLongClickListener(OnClickListener);
4. checkBox.setOnCheckedChangeListener(listener);
5. listview.setOnItemClickListener(OnItemClickListener);
6. listview.setOnScrollListener(OnScrollListener);
7. imageView.setOnTouchListener()
8. fragment public void onHiddenChanged(boolean hidden) {}
9. setOnSeekBarChangeListener
10.OntouchListener
11.SeekBar.setOnSeekBarChangeListener(Listener)

04. Manager

01. smsManager

實現:發送短信


SmsManager smsManager = SmsManager.getDefault();
//發送短信是通過API 提供的短信管理器實現的
//通過SmsManager 的靜態方法獲取對象
SmsManager smsManager = SmsManager.getDefault();
//短信長度超過一定的限制後需要切割成多條分批發送
//一定要使用SmsManager 對象提供的divideMessage(String)方法切割
ArrayList<String> parts = smsManager.divideMessage(sms);
smsManager.sendMultipartTextMessage(num, null, parts, null, null);

02. TelephoneManager

實現:監聽電話狀態


TelephonyManager tm = (TelephonyManager) context.getSystemServer(Context.TELEPHONY_SERVICE);
//電話狀態的監聽
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
//SIM卡的綁定:權限:android.permission.READ_PHONE_STATE
String simSerialNumber = tm.getSimSerialNumber();

03. connectivityManager
實現:獲取網絡狀態


ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

04. WindowManager

實現:獲取屏幕的寬高


// 方式1:獲取屏幕的寬高
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;
//方式2: Activity中獲取屏幕的寬高,
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
//方式3:推薦該方式.
DisplayMetrics metrics =getWindowManager().getDefaultDisplay().getDisplayMetrics();
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;

05. FragmentManager


FragmentManager fragmentManager = getSupportFragmentManager();

06. LocationManager GPS
實現:獲取GPS位置服務


LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
String provider = LocationManager.GPS_PROVIDER;

long minTime = 0;
float minDistance = 0;
lm.requestLocationUpdates(provider, minTime, minDistance, this);
public void onLocationChanged(Location location) {
    // 經度
    double longitude = location.getLongitude();
    // 緯度
    double latitude = location.getLatitude();
    System.out.println(
            "onLocationChanged:" + ",longitude:" + longitude + ",latitude:" + latitude);
}

protected void onPause() {
    super.onPause();
    // 取消監聽, 節約資源
    lm.removeUpdates(this);
}

07. DevicePolicyManager

實現:獲取設備管理員權限,鎖屏,擦除數據


DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);

如用模擬器,請使用5.0以下版本測試一鍵鎖屏

  • 實現 : 參考/docs/guide/topics/admin/device-admin.html頁面

1. 創建一個DeviceAdminReceiver 的子類, 例如LockDeviceAdminReceiver

2. 在manifest文件中註冊這個新創建的廣播接收者,模板代碼
    <receiver
        android:name="com.itheima.lockapp.LockDeviceAdminReceiver"
        android:description="@string/device_admin_description" // 本功能的描述, 需自己創建
        android:label="@string/app_name" // 軟件名稱
        android:permission="android.permission.BIND_DEVICE_ADMIN" >
        <meta-data
            android:name="android.app.device_admin"
            android:resource="@xml/device_admin" /> // 該文件用來聲明本軟件所要使用的安全策略, 需自己創建文件
        <intent-filter>
            <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
        </intent-filter>
    </receiver>

>
3. 在res目錄下, 新建一個目錄,名爲xml, 在xml目錄下新建一個xml文件, 文件名必須和manifest文件中聲明的receiver的android:resource節點值一致. 文件內容如下, 需根據實際業務需要進行增刪




















>
4. 實現功能, 監聽狀態
public class MainActivity extends Activity {
private static final int REQUEST_CODE_ENABLE_ADMIN = 100;
private DevicePolicyManager dpm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 獲取設備策略管理器
dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
// 創建自定義Receiver的唯一標識
ComponentName admin = new ComponentName(this, LockDeviceAdminReceiver.class);
// 判斷自定義的Receiver是否已經被激活
boolean isAdaminActive = dpm.isAdminActive(admin);
// 如果已經被激活,直接鎖屏並關閉當前頁面
if (isAdaminActive) {
dpm.lockNow();
finish();
} else {
// 如果沒有被激活,彈窗提示用戶去激活系統管理員
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
getString(R.string.device_admin_description));
startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_ENABLE_ADMIN) {
// 激活成功, 鎖屏並關閉當前頁面
if (resultCode == Activity.RESULT_OK) {
dpm.lockNow();
finish();
// 激活失敗, 直接退出
} else if (resultCode == Activity.RESULT_CANCELED) {
finish();
}
}
}
}

* 需求 : 激活系統管理員以後直接卸載程序, 不彈出警告窗口
* 實現 : 判斷當前軟件是否已經激活系統管理員, 如果激活了, 先取消. 之後調用隱式意圖卸載程序
* 代碼 : 

public class UninstallActivity extends Activity {
    private DevicePolicyManager dpm;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_uninstall);
        // 獲取設備策略管理器
        dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
        // 創建自定義Receiver的唯一標識
        ComponentName admin = new ComponentName(this, LockDeviceAdminReceiver.class);
        // 判斷自定義的Receiver是否已經被激活
        boolean isAdaminActive = dpm.isAdminActive(admin);
        // 如果激活了, 先取消設備管理器
        if (isAdaminActive) {
            dpm.removeActiveAdmin(admin);
        }
        // 發送隱式意圖,卸載當前應用
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_DELETE);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
        finish();
    }
}
// manifest文件
<activity
    android:name=".UninstallActivity"
    android:label="一鍵卸載"
    android:launchMode="singleInstance" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

* 需求 : 實現遠程擦除數據和鎖屏的功能
* 實現 : 通過DevicePolicyManager的wipeData()方法和lockNow()實現
* 代碼 :

DevicePolicyManager dpm = (DevicePolicyManager) context
        .getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);
abortBroadcast();
DevicePolicyManager dpm = (DevicePolicyManager) context
        .getSystemService(Context.DEVICE_POLICY_SERVICE);
//設置密碼.
dpm.resetPassword("123", DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);

08. ActivityManager

實現:查詢當前運行的服務,正在運行的進程,內存使用情況,殺死進程


ActivityManager am = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE);
//獲取服務的狀態
public static boolean isServiceRunning(Context context,
        Class<? extends Service> clazz) {
    boolean flag = false;
    // 獲取ActivityManager
    ActivityManager am = (ActivityManager) context
            .getSystemService(Context.ACTIVITY_SERVICE);
    // 獲取正在運行的服務
    List<RunningServiceInfo> lis = am.getRunningServices(Integer.MAX_VALUE);
    // 遍歷集合
    for (RunningServiceInfo info : lis) {
        // 獲取服務的名字
        String className = info.service.getClassName();
        // 如果有服務和我們的服務名字一致, 說明正在運行
        if (className.equals(clazz.getName())) {
            flag = true;
        }
    }
    return flag;
}


**不能在Android5.0以上機器使用以下代碼**
* 正在運行的進程可以通過ActivityManager.getRunningAppProcesses()方法獲得

* 內存使用情況可以通過ActivityManager.getMemoryInfo()方法獲取

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();
// 獲取總共可運行內存個數
PackageManager pm = getPackageManager();

## 0902_版本適配獲得內存信息
* 需求 :  判斷當前系統的版本, 對於低版本系統使用讀取系統文件的方式獲取總內存大小
* 實現 : * 讀取系統的/proc/meminfo文件獲取內存信息
private void initRam() {
    // 獲取內存信息
    MemoryInfo outInfo = new MemoryInfo();
    am.getMemoryInfo(outInfo);
    //可用內存
    long availMem = outInfo.availMem;
    long totalMem = 0;
    int sdkInt = Build.VERSION.SDK_INT;
    // 高版本系統,直接讀取
    if (sdkInt >= Build.VERSION_CODES.JELLY_BEAN) {
        totalMem = outInfo.totalMem;
    } else {
        // 低版本系統讀取系統文件
        File file = new File("/proc/meminfo");
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(file));
            String readLine = br.readLine();
            readLine = readLine.replace("MemTotal:", "");
            readLine = readLine.replace("kB", "");
            readLine = readLine.trim();
            totalMem = Long.valueOf(readLine) * 1024;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(br);
        }

    }
//已用內存
long usedMem = totalMem - availMem;
//
private void initAdapter() {
    ArrayList<AppRAMBean> list = new ArrayList<AppRAMBean>();
    // 遍歷所有正在運行的進程
    for (RunningAppProcessInfo info : runningAppProcesses) {
        AppRAMBean bean = new AppRAMBean();
        // 獲取包名
        String pkgName = info.processName;
        // 獲取應用圖標.如果有就用應用自己的,沒有就用默認的
        try {
            Drawable icon = packageManager.getApplicationIcon(pkgName);
            bean.icon = icon;
        } catch (NameNotFoundException e) {
            bean.icon = getResources().getDrawable(R.drawable.ic_launcher);
            e.printStackTrace();
        }

        try {
            ApplicationInfo applicationInfo = packageManager.getApplicationInfo(pkgName, 0);
            // 獲取應用的名稱
            CharSequence applicationLabel = packageManager.getApplicationLabel(applicationInfo);
            bean.name = applicationLabel.toString();
            // 獲取是否是系統應用
            int flag = applicationInfo.flags;
            if ((flag & ApplicationInfo.FLAG_SYSTEM) == ApplicationInfo.FLAG_SYSTEM) {
                bean.isSystem = true;
            } else {
                bean.isSystem = false;
            }
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        // 獲取當前進程所佔用的內存信息
        int pid = info.pid;
        android.os.Debug.MemoryInfo processMemoryInfo =
                activityManager.getProcessMemoryInfo(new int[] {pid})[0];
        int totalPss = processMemoryInfo.getTotalPss();
        bean.usedRam = totalPss*1024
    }
}

* 實現 : 清理進程的方法 ActivityManager.killBackgroundProcesses(String pkgName). 
* 殺死後臺進程要添加權限 android.permission.KILL_BACKGROUND_PROCESSES

09. AssetsManager 獲取資產目錄路徑


getAssets

10. PackageManager

實現:版本信息,應用信息,包名,總進程數

  • 1.獲取版本信息,應用的信息:名稱,圖標,安裝路徑,包名,UID(獲取流量).2.判斷安裝位置.判斷系統應用,
  • 3.通過包名,打開程序,卸載程序,打開應用詳情頁面.4.通過文件的路徑,可以跳轉安裝程序頁面.

PackageManager pm = context.getPackageManager();

// 獲取當前包的版本號,可用於升級.
PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
String versionName = packageInfo.versionName;

// 獲取當前手機安裝的所有應用信息
List<ApplicationInfo> list = pm.getInstalledApplications(0);
for (ApplicationInfo info : list) {
    // 獲取應用的名稱
    CharSequence applicationLabel = pm.getApplicationLabel(info);

    // 獲取應用的圖標
    Drawable icon = pm.getApplicationIcon(info);

    // 獲取應用的安裝路徑
    String sourceDir = info.sourceDir;
    File file = new File(sourceDir);
    // 獲取包名
    bean.pkgName = info.packageName;

    // 獲去應用的uid,可用於統計流量
    int uid = info.uid;

    // 獲取應用的大小
    long totalSpace = file.length();
    bean.size = Formatter.formatFileSize(this, totalSpace);

    // 判斷應用的安裝位置
    if (sourceDir.startsWith("/mnt/asec")) {
        bean.isOnSD = true;
    } else {
        bean.isOnSD = false;
    }
}

//判斷出程序是否是系統程序
// 方法一 : 判斷ApplicationInfo.sourceDir 是否以"/system" 開頭
if (sourceDir.startsWith("/system")) {
    bean.isSystemApp = true;
} else {
    bean.isSystemApp = false;
}

//方法二 : 判斷ApplicationInfo.FLAG_SYSTEM與運算的結果
int flags = info.flags;

if ((flags & ApplicationInfo.FLAG_SYSTEM) == ApplicationInfo.FLAG_SYSTEM) {
    bean.isSystemApp = true;
} else {
    bean.isSystemApp = false;
}

// 跳轉應用信息詳情界面,包名
 Intent intent = new Intent();
 intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
 intent.addCategory("android.intent.category.DEFAULT");
 intent.setData(Uri.parse("package:" + itemBean.pkgName));
 startActivity(intent);

//打開程序,包名
intent = getPackageManager().getLaunchIntentForPackage(itemBean.pkgName);
startActivity(intent); 

//安裝程序,文件的目錄
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.parse("file:" + file.getAbsolutePath()),
        "application/vnd.android.package-archive");
startActivityForResult(intent, REQ_CODE_INSTALL_APP);

// 卸載應用,包名
Uri packageURI = Uri.parse("package:" + itemBean.pkgName);
Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
startActivity(uninstallIntent);

// 註冊廣播,拿到卸載應用的包名
receiver = new UninstallReceiver();
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
registerReceiver(receiver, filter);
// 廣播類
class UninstallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //獲得廣播的內容,package:+ 包名
        String dataString = intent.getDataString();
        //拿到包名
        dataString = dataString.replace("package:", "");
    }
}
  • 需求 : 獲取流量使用的詳細數據. 此功能只能在低版本手機上測試,不能使用模擬器
  • 實現 :
    • 默認情況下,每一個應用的流量使用情況都會儲存在”/proc/uid_stat/uid/”目錄下的兩個文件中,tcp_rcv文件記錄收到的流量,tcp_snd文件記錄發送的流量.此方法獲取的數據比較準確,但是在高版本手機上無法讀取到這兩個文件.在改版的手機上因爲目錄可能被更改,也會導致無法使用
    • 通過TrafficStats.getUidRxBytes獲取收到的流量,通過TrafficStats.getUidTxBytes獲取發送的流量,但是這種方法獲取的數據並不準確

PackageManager pm = getPackageManager();
List<ApplicationInfo> lists = pm.getInstalledApplications(0);
for (ApplicationInfo info : lists) {
    //獲取應用的標識符uid
    int uid = info.uid;
    // 此方法獲取的數據並不準確
    long uidRxBytes = TrafficStats.getUidRxBytes(uid);
    long uidTxBytes = TrafficStats.getUidTxBytes(uid);

// 此方法比較準確,但是在高版本手機上無法使用.
// 在改版的手機上因爲目錄可能被更改,也會導致無法使用
private long getReceive(int uid) {
    //收到的流量
    File file = new File("/proc/uid_stat/" + uid + "/tcp_rcv");
    //發送的流量
    //File file = new File("/proc/uid_stat/" + uid + "/tcp_snd");
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(file));
        String readLine = br.readLine();
        return Long.valueOf(readLine);
    } catch (Exception e) {
        e.printStackTrace();
        return 0;
    } finally {
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            br = null;
        }
    }


**不能在Android5.0以上機器使用以下代碼**
* 總進程數可以通過PackageManager.getInstalledPackages(0)方法的返回值獲取
// 獲取手機上所有已安裝的應用
List<PackageInfo> installedPackages = pm.getInstalledPackages(0);
// 創建集合
Set<String> set = new HashSet<String>();
for (PackageInfo packageInfo : installedPackages) {
    // 獲取所有Application節點的processName
    String processName = packageInfo.applicationInfo.processName;
    set.add(processName);
    // 獲取所有Activity節點的processName
    ActivityInfo[] activities = packageInfo.activities;
    if (activities != null) {
        for (ActivityInfo activityInfo : activities) {
            String processName2 = activityInfo.processName;
            set.add(processName2);
        }
    }
    // 獲取所有Service節點的processName
    ServiceInfo[] services = packageInfo.services;
    if (services != null) {
        for (ServiceInfo serviceInfo : services) {
            set.add(serviceInfo.processName);
        }
    }
    // 獲取所有receiver節點的processName
    ActivityInfo[] receivers = packageInfo.receivers;
    if (receivers != null) {
        for (ActivityInfo activityInfo : receivers) {
            set.add(activityInfo.processName);
        }
    }
    // 獲取所有Provider節點的processName
    ProviderInfo[] providers = packageInfo.providers;
    if (providers != null) {
        for (ProviderInfo providerInfo : providers) {
            set.add(providerInfo.processName);
        }
    }
    ssv_num.setFreeText("可運行" + set.size() + "個");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章