Intent&Context&Listener&Manager
- Intent數據類型
- Context區別
- Listener
- Manager
01.Intent攜帶的數據類型
- 8種基本數據類型以及數組形式以及String
- 實現了序列化接口的對象
- Serializable(Sun),聲明爲transient 的變量不會被序列化
- 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的區別
- Activity 一個Activity對應一個Context
- Service 一個Service對應一個Context
- BroadCastReceiver中的onReceive(Context)方法執行完了了,這裏的Context就完了
- 在內容提供者中獲得上下文getContext()
- getApplicationContext()全局上下文
- 在fragment中可以通過getActivity()獲得
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() + "個");
}