本帖最后由 小鲁哥哥 于 2017-4-12 14:30 编辑
Android课程同步笔记day09:Android应用之安全卫士
应用程序排序显示前面我们已经可以将所有的应用程序显示出来了,不过现在我们需要将用户程序和系统程序给区分起来,让所有的应用程序进行一个排序,让用户程序显示在前面。这里可以直接使用Collections.sort方法: 在AppManagerActivity的initData方法中增加如下一段代码 [Java] 纯文本查看 复制代码 // 剩余
mPsvSD.setRightText(Formatter.formatFileSize(this, sdFreeSpace) + "可用");
mPsvSD.setLeftText(Formatter.formatFileSize(this, sdUsedSpace) + "已用");
mPsvSD.setProgress(sdProgress);
mLoadinView.setVisibility(View.VISIBLE);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
mDatas = AppProvider.getAllApps(AppManagerActivity.this);
// 排序
Collections.sort(mDatas, new Comparator<AppBean>() {
@Override
public int compare(AppBean lhs, AppBean rhs) {
// 用户程序排在前面
boolean lhsSystem = lhs.isSystem;
boolean rhsSystem = rhs.isSystem;
int lhsInt = lhsSystem ? 1 : 0;
int rhsInt = rhsSystem ? 1 : 0;
return lhsInt - rhsInt;
}
});
// 查找用户程序的个数,系统程序的个数
for (AppBean bean : mDatas) {
if (bean.isSystem) {
mSystemCount++;
} else {
mUserCount++;
}
}
// 主线程中执行
runOnUiThread(new Runnable() {
@Override
public void run() {
mLoadinView.setVisibility(View.GONE);
// 给listView设置adapter
mAdapter = new AppAdapter();
mListView.setAdapter(mAdapter);
}
});
}
}).start(); 第二种方式实现排序: 这里也可以使用Collections.sort(mDatas);只传一个参数的方法,让AppInfo对象去实现Comparable接口: [Java] 纯文本查看 复制代码 public class AppInfo implements Comparable<AppInfo> {
// Drawable 不仅仅表示图片表示资源文件表示的范围更广泛
// bitmap 只能单纯表示图片
public Drawable icon;// 应用的icon
public String name;// 名称
public boolean isInstallSD;// 是否安装在sd卡
public long space;// 使用的空间大小
public boolean isSystem;// 表示是否是系统应用
public String packageName;// 应用的包名
@Override
public int compareTo(AppInfo another) {
boolean lhsSystem = isSystem;
boolean rhsSystem = another.isSystem;
int thisInt = lhsSystem ? 1 : 0;
int anotherInt = rhsSystem ? 1 : 0;
return thisInt - anotherInt;//小于0 左边在前面
}
} ListView条目头的添加
为了实现效果图中的效果,在listview条目顶部添加一个条目类型的效果,这里引入一个三方的库,添加步骤如下
要注意的是库文件必须和自己的应用文件在同一个目录下。 接下来修改activity_app_manager中的布局,将listview替换为三方的listview如下:
[XML] 纯文本查看 复制代码 <se.emilsjolander.stickylistheaders.StickyListHeadersListView
android:id="@+id/am_listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include layout="@layout/include_loading" />
在activity中找到控件设置adapter。不过adpater必须得实现三方库中的接口:
实现接口中的两个方法 :
[Java] 纯文本查看 复制代码 @Override
public View getHeaderView(int position, View convertView,
ViewGroup parent) {
HeaderViewHolder holder = null;
if (convertView == null) {
// 没有复用
convertView = View.inflate(AppManagerActivity.this,
R.layout.item_header, null);
holder = new HeaderViewHolder();
convertView.setTag(holder);
holder.tvTitle = (TextView) convertView
.findViewById(R.id.item_header_tv_title);
} else {
holder = (HeaderViewHolder) convertView.getTag();
}
// set header text as first char in name
AppInfo bean = mDatas.get(position);
if (bean.isSystem) {
holder.tvTitle.setText("系统程序(" + mSystemCount + ")");
} else {
holder.tvTitle.setText("用户程序(" + mUserCount + ")");
}
return convertView;
}
@Override
public long getHeaderId(int position) {
// 返回值代表一种类型的头
AppInfo bean = mDatas.get(position);
return bean.isSystem ? 0 : 1;
}
private static class HeaderViewHolder {
TextView tvTitle;
}
以及用户程序个数和系统程序个数在initData获取到数据后计算出来:
Headerview头条目的布局文件很简单就一个textview: [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:background="#ffD6D4D7"
android:orientation="vertical" >
<TextView
android:id="@+id/item_header_tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="头"
/>
</LinearLayout> 现上诉代码后运行起来的效果如下:
ListView 条目的小气泡当选中ListView 的某一个应用程序时,程序的下方会浮出一个小气泡,提供卸载、打开、分享、信息四个选项可以对程序进行操作,该条目的布局如下所示: [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/pop_bg"
android:orientation="horizontal" >
<TextView
android:id="@+id/popup_tv_unistall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:drawablePadding="2dp"
android:drawableTop="@drawable/ic_uninstall"
android:gravity="center_horizontal"
android:text="卸载"
android:textSize="12sp" />
<TextView
android:id="@+id/popup_tv_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:drawablePadding="2dp"
android:drawableTop="@drawable/ic_open"
android:gravity="center_horizontal"
android:text="打开"
android:textSize="12sp" />
<TextView
android:id="@+id/popup_tv_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:drawablePadding="2dp"
android:drawableTop="@drawable/ic_share"
android:gravity="center_horizontal"
android:text="分享"
android:textSize="12sp" />
<TextView
android:id="@+id/popup_tv_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:drawablePadding="2dp"
android:drawableTop="@drawable/ic_info"
android:gravity="center_horizontal"
android:text="信息"
android:textSize="12sp" />
</LinearLayout> 上述布局文件中,主要使用了一个线性布局,线性布局中放置了4个TextView 控件,分别用于展示这四个按钮的文字提示、功能图标。此外,线性布局的背景使用一个点9 图,可以进行横向纵向的拉伸效果。 ListView 的点击事件 当点击ListView 的条目时,会弹出小气泡,因此这里使用popupwindow来展示是最合适的选择,代码如下: [Java] 纯文本查看 复制代码 @Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// View view:点击的条目
// 显示提示框,(卸载,打开,分享,信息)
// popupwindow使用的步骤
// 1. 去写内容的布局
View contentView = View.inflate(this, R.layout.popup_app, null);
// 2. 创建PopupWindow
final PopupWindow window = new PopupWindow(contentView,
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// 额外的设置(让popupWindow只弹出一个)
window.setFocusable(true);// 获得焦点
window.setBackgroundDrawable(new ColorDrawable());
window.setTouchable(true);
// 动画
window.setAnimationStyle(R.style.popAnimation);
// 3. 显示PopupWindow
//第一个参数:展示在某某控件的下方
//第二个参数:表示x 轴的偏移量
//第三个参数:表示y 轴的偏移量
System.out.println("view height:"+view.getHeight());
window.showAsDropDown(view, 80, -view.getHeight());
} 其中为了让用户的体验效果更好,这里让弹出来的popupwindow具有一个动画效果,这里使用了一种动画的样式popAnimation: [XML] 纯文本查看 复制代码 <style name="popAnimation">
<item name="android:windowEnterAnimation">@anim/pop_enter</item>
<item name="android:windowExitAnimation">@anim/pop_exit</item>
</style> 在anim文件夹下创建对应的动画资源文件pop_enter.xml: [XML] 纯文本查看 复制代码 <set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromXDelta="100%"
android:interpolator="@interpolator/overshoot"
android:toXDelta="0" />
<alpha
android:duration="@android:integer/config_shortAnimTime"
android:fromAlpha="0.5"
android:interpolator="@interpolator/decelerate_cubic"
android:toAlpha="1.0" />
</set> 其中android:interpolator="@interpolator/overshoot"是动画差值器,可以使动画产生一种加速度和方向上的改变效果,而且系统自带就实现好了这些xml可以在系统源码中去进行拷贝。pop_exit.xml: [XML] 纯文本查看 复制代码 <set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >
<translate
android:duration="@android:integer/config_shortAnimTime"
android:fromXDelta="0"
android:interpolator="@interpolator/anticipate"
android:toXDelta="100%" />
<alpha
android:duration="@android:integer/config_shortAnimTime"
android:fromAlpha="1.0"
android:interpolator="@interpolator/accelerate_cubic"
android:toAlpha="0.0" />
</set> 卸载,打开,详情实现Popupwindow中一共有四个textview,分别初始化这些控件,然后给他设置点击事件去实现对应的功能: 卸载 [Java] 纯文本查看 复制代码 // 初始化View
TextView tvUninstall = (TextView) contentView
.findViewById(R.id.popup_tv_unistall);
TextView tvOpen = (TextView) contentView
.findViewById(R.id.popup_tv_open);
TextView tvShare = (TextView) contentView
.findViewById(R.id.popup_tv_share);
TextView tvInfo = (TextView) contentView
.findViewById(R.id.popup_tv_info);
//获取到当前点击的应用程序包名
AppInfo bean = mDatas.get(position);
final String packageName = bean.packageName;
if (bean.isSystem) {
//如果是系统应用则隐藏该功能
tvUninstall.setVisibility(View.GONE);
}
// 点击卸载
tvUninstall.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("android.intent.action.DELETE");
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
// 隐藏popupwindow
window.dismiss();
}
}); 注意系统的应用程序是没法进行卸载的,所以要记得加上判断。 如果当用户卸载成功后返回到软件管家界面,这时我们应该还要更新当前的界面;所以需要注册一个应用程序卸载成功的广播: [Java] 纯文本查看 复制代码 private void initEvent() {
mListView.setOnItemClickListener(this);
// 注册广播接受者,应用卸载
mUninstallReceiver = new PackageUninstallReceiver();
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);// 包卸载的行为
filter.addDataScheme("package");
registerReceiver(mUninstallReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 注销
unregisterReceiver(mUninstallReceiver);
}
private class PackageUninstallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String dataString = intent.getDataString();
// dataString--> package:包名
// 包名 --》 mDatas遍历 --》发现有包---》移除---》UI更新
String packageName = dataString.replace("package:", "");
ListIterator<AppInfo> iterator = mDatas.listIterator();
while (iterator.hasNext()) {
AppInfo bean = iterator.next();
// 比对
if (bean.packageName.equals(packageName)) {
// 有的--》移除
iterator.remove();
break;
}
}
// UI更新,adapter更新
mAdapter.notifyDataSetChanged();
}
} 打开 由于有些应用程序没有启动项,可能只是一个服务进程或者后台进程则就不能通过api去打开该应用,需要隐藏掉该功能: [AppleScript] 纯文本查看 复制代码 PackageManager pm = getPackageManager();
final Intent intent = pm.getLaunchIntentForPackage(packageName);
if (intent == null) {
// 没有启动项
tvOpen.setVisibility(View.GONE);
}
// 打开
tvOpen.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 打开应用
startActivity(intent);
// 隐藏popupwindow
window.dismiss();
}
}); 查看详情 通过隐式意图直接打开详情界面: [Java] 纯文本查看 复制代码 // 查看信息
tvInfo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
// 隐藏popupwindow
window.dismiss();
}
}); 社会化分享
最后一个功能分享,这里我们借助了三方平台的sdk来进行分享;分享的效果图如下:
官网的教程链接如下: 按照官网的教程一步一步配置下来即可快速实现,这里只贴出点击分享按钮的代码实现: [Java] 纯文本查看 复制代码 // 社会化分享
tvShare.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showShare(packageName, packageName);
// 隐藏popupwindow
window.dismiss();
}
});
private void showShare(String title, String text) {
ShareSDK.initSDK(this);
OnekeyShare oks = new OnekeyShare();
// 关闭sso授权
oks.disableSSOWhenAuthorize();
// 分享时Notification的图标和文字 2.5.9以后的版本不调用此方法
// oks.setNotification(R.drawable.ic_launcher,
// getString(R.string.app_name));
// title标题,印象笔记、邮箱、信息、微信、人人网和QQ空间使用
oks.setTitle(title);
// titleUrl是标题的网络链接,仅在人人网和QQ空间使用
// oks.setTitleUrl("http://sharesdk.cn");
// text是分享文本,所有平台都需要这个字段
oks.setText(text);
// imagePath是图片的本地路径,Linked-In以外的平台都支持此参数
oks.setImagePath("/sdcard/test.jpg");// 确保SDcard下面存在此张图片
// url仅在微信(包括好友和朋友圈)中使用
// oks.setUrl("http://sharesdk.cn");
// comment是我对这条分享的评论,仅在人人网和QQ空间使用
// oks.setComment("我是测试评论文本");
// site是分享此内容的网站名称,仅在QQ空间使用
// oks.setSite(getString(R.string.app_name));
// siteUrl是分享此内容的网站地址,仅在QQ空间使用
// oks.setSiteUrl("http://sharesdk.cn");
// 启动分享GUI
oks.show(this);
} Include标签
整个软件管家的逻辑和界面都已经实现完了,接下来需要优化一点的是当应用程序太多,数据太多在获取的时候可能会阻塞主线程,导致不良好的用户体验;所以最好是将之前在骚扰拦截模块就已经实现好的进度条加载进来提示用户,Xml为
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/include_ll_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical"
android:visibility="gone" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/loading_bg" />
<TextView
style="@style/textNormal"
android:text="加载中..." />
</LinearLayout> 因为这样的进度提示可能很多界面都会用到,所以单独抽取出来做成一个单独的xml布局;在需要用到的界面通过include标签引入即可;接下来在软件管家界面的布局中引入进度条提示: Activity中initdata方法中获取数据的逻辑单独放一个子线程中去执行,执行之前显示进度条;UI显示完全后再隐藏,部分代码为: [Java] 纯文本查看 复制代码 mLoadinView.setVisibility(View.VISIBLE);
new Thread() {
public void run() {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获取所有安装的应用信息
mDatas = AppProvider.getAllApps(AppManagerActivity.this);
Collections.sort(mDatas);
// 查找用户程序的个数,系统程序的个数
for (AppInfo bean : mDatas) {
if (bean.isSystem) {
mSystemCount++;
} else {
mUserCount++;
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
mLoadinView.setVisibility(View.GONE);
// 给listView设置adapter
mAdapter = new AppAdapter();
mListView.setAdapter(mAdapter);
}
});
};
}.start(); 进程管理 进程管理模块主要用于查看当前开启多少进程服务,其中包含用户进程个数和系统进程个数,我们可以选择清理某个进程,也可以选择清理所有进程,该模块界面效果如图所示: 整体布局xml [XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:itheima="http://schemas.android.com/apk/res/com.itheima.zphuanlove"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
style="@style/titleBarStyle"
android:text="进程管理" />
<ImageView
android:id="@+id/pm_iv_clean"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentRight="true"
android:scaleType="center"
android:src="@drawable/btn_clean_selector" />
</RelativeLayout>
<com.itheima.zphuanlove.view.ProgressStateView
android:id="@+id/pm_psv_proces"
android:layout_width="match_parent"
android:layout_height="wrap_content"
itheima:psvText="进程数:" />
<com.itheima.zphuanlove.view.ProgressStateView
android:id="@+id/pm_psv_memory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
itheima:psvText="内存:" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1000" >
<se.emilsjolander.stickylistheaders.StickyListHeadersListView
android:id="@+id/pm_listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include layout="@layout/include_loading" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal" >
<Button
android:id="@+id/pm_btn_all"
style="@style/btnCancelNormal"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:text="全选" />
<Button
android:id="@+id/pm_btn_reverse"
style="@style/btnCancelNormal"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:text="反选" />
</LinearLayout>
</LinearLayout> 界面有了,接下来需要准备数据进行界面展示;这里创建一个ProcessProvider.java类来获取里面主要涉及到有获取运行的进程个数,总共的进程个数等方法 [Java] 纯文本查看 复制代码 public class ProcessProvider {
/**
* 获得运行的进程数
*
* @param context
* @return
*/
public static int getRunningProcessCount(Context context) {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
// 获得正在运行的进程
List<RunningAppProcessInfo> list = am.getRunningAppProcesses();
return list.size();
}
/**
* 统计可有的进程数
*
* @param context
* @return
*/
public static int getTotalProcessCount(Context context) {
PackageManager pm = context.getPackageManager();
Set<String> set = new HashSet<String>();
List<PackageInfo> packages = pm.getInstalledPackages(0);
for (PackageInfo info : packages) {
// application,activity,service,receiver,provider进程名
// 相同的只统计一次
// application
ApplicationInfo applicationInfo = info.applicationInfo;
String processName = applicationInfo.processName;
set.add(processName);
// activity
ActivityInfo[] activities = info.activities;
if (activities != null) {
for (ActivityInfo activityInfo : activities) {
set.add(activityInfo.processName);
}
}
// service
ServiceInfo[] services = info.services;
if (services != null) {
for (ServiceInfo serviceInfo : services) {
set.add(serviceInfo.processName);
}
}
// receiver
ActivityInfo[] receivers = info.receivers;
if (receivers != null) {
for (ActivityInfo activityInfo : receivers) {
set.add(activityInfo.processName);
}
}
// provider
ProviderInfo[] providers = info.providers;
if (providers != null) {
for (ProviderInfo providerInfo : providers) {
set.add(providerInfo.processName);
}
}
}
return set.size();
}
/**
* 获得使用的内存信息
*
* @param context
* @return
*/
public static long getUsedMemory(Context context) {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
long total = 0;
// 获得正在运行的进程
List<RunningAppProcessInfo> list = am.getRunningAppProcesses();
for (RunningAppProcessInfo info : list) {
// 进程id
int pid = info.pid;
MemoryInfo memoryInfo = am.getProcessMemoryInfo(new int[] { pid })[0];
long memory = memoryInfo.getTotalPss() * 1024;
total += memory;
}
return total;
}
public static long getTotalMemory() {
File file = new File("/proc/meminfo");
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
// MemTotal: 513492 kB
String readLine = reader.readLine();
readLine = readLine.replace("MemTotal:", "");
readLine = readLine.replace("kB", "");
readLine = readLine.trim();
long result = Long.parseLong(readLine) * 1024;
return result;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
} 主界面设置进程数据和内存数据的代码逻辑如下: [Java] 纯文本查看 复制代码 public class ProcessManagerActivity extends Activity {
private ProgressStateView mPsvProcess;
private ProgressStateView mPsvMemory;
private StickyListHeadersListView mListView;
private Button mBtnAll;
private Button mBtnReverse;
private ImageView mIvClean;
private View mLoadingView;
private int mRunningProcessCount;
private int mTotalProcessCount;
private long mUsedMemory;
private long mTotalMemory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_process_manager);
initView();
initData();
}
private void initView() {
mPsvProcess = (ProgressStateView) findViewById(R.id.pm_psv_proces);
mPsvMemory = (ProgressStateView) findViewById(R.id.pm_psv_memory);
mListView = (StickyListHeadersListView) findViewById(R.id.pm_listview);
mBtnAll = (Button) findViewById(R.id.pm_btn_all);
mBtnReverse = (Button) findViewById(R.id.pm_btn_reverse);
mIvClean = (ImageView) findViewById(R.id.pm_iv_clean);
mLoadingView = findViewById(R.id.include_ll_loading);
}
private void initData() {
// 1.设置进程数据
mRunningProcessCount = ProcessProvider.getRunningProcessCount(this);
mTotalProcessCount = ProcessProvider.getTotalProcessCount(this);
loadProcess();
// 2. 已经使用了的内存(当前运行的进程销毁的内存总和),手机总内存是多大
mUsedMemory = ProcessProvider.getUsedMemory(this);
mTotalMemory = ProcessProvider.getTotalMemory();
loadMemory();
}
private void loadProcess() {
int processProgress = (int) (mRunningProcessCount * 100f
/ mTotalProcessCount + 0.5f);
mPsvProcess.setLeftText("正在运行" + mRunningProcessCount + "个");
mPsvProcess.setRightText("可有进程" + mTotalProcessCount + "个");
mPsvProcess.setProgress(processProgress);
}
private void loadMemory() {
long freeMemory = mTotalMemory - mUsedMemory;
int memoryProgress = (int) (mUsedMemory * 100f / mTotalMemory + 0.5f);
mPsvMemory.setLeftText("占用内存:"
+ Formatter.formatFileSize(this, mUsedMemory));
mPsvMemory.setRightText("剩余内存:"
+ Formatter.formatFileSize(this, freeMemory));
mPsvMemory.setProgress(memoryProgress);
}
}
|