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() + "个");
}