还是继续复习我的安卓基础吧,毕竟基础才是最重要的
这一篇文章将会用到复杂的listview,和获取系统软件信息,还有给Listview加动画效果.
先看看布局吧,源码在后面提供下载,只是一个包,因为我是拿测试项目在演示。
① 布局的建立
布局很简单 我直接贴源码吧 因为怕有些手机装的APP过多,所以加入了一个progressbar
<?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="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/tv_avail_rom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="内存可用:"
android:textColor="#000000" />
<TextView
android:id="@+id/tv_avail_sd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="SD卡可用:"
android:textColor="#000000" />
</RelativeLayout>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="@+id/ll_loading"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="invisible" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载程序信息..." />
</LinearLayout>
<ListView
android:overScrollMode="never"
android:fastScrollEnabled="true"
android:id="@+id/lv_app_manager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>
<TextView
android:id="@+id/tv_status"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="用户程序:6个"
android:textColor="#ffffff"
android:background="#ff888888"
/>
</FrameLayout>
</LinearLayout>
②建立获取系统软件信息类
要得到系统软件信息,首先要通过一个类,PackageManager,里面可以获得很多东西
一 、PackageManager的介绍
主要是管理应用程序包,通过它就可以获取应用程序信息。
二、利用PackageManager得到我们需要的软件信息
package com.example.Darkbutton.Appmanager;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
/**
* @author xiaoxin007
* 2014-12-6下午8:18:58
* TODO 业务方法,提供手机里面安装的所有的应用程序信息
*/
public class AppInfoProvider {
/**
* 获取所有的安装的应用程序信息。
* @param context 上下文
* @return
*/
public static List<AppInfo> getAppInfos(Context context){
//1.获得一个包管理器
PackageManager pm = context.getPackageManager();
//2.所有的安装在系统上的应用程序包信息。
List<PackageInfo> packInfos = pm.getInstalledPackages(0);
//3.建立一个实体类 存储东西
List<AppInfo> appInfos = new ArrayList<AppInfo>();
//4.遍历
for(PackageInfo packInfo : packInfos){
AppInfo appInfo = new AppInfo();
//packInfo 相当于一个应用程序apk包的清单文件
String packname = packInfo.packageName;
Drawable icon = packInfo.applicationInfo.loadIcon(pm);
String name = packInfo.applicationInfo.loadLabel(pm).toString();
int flags = packInfo.applicationInfo.flags;//应用程序信息的标记 相当于用户提交的答卷
if((flags&ApplicationInfo.FLAG_SYSTEM)==0){
//用户程序
appInfo.setUserApp(true);
}else{
//系统程序
appInfo.setUserApp(false);
}
if((flags&ApplicationInfo.FLAG_EXTERNAL_STORAGE)==0){
//手机的内存
appInfo.setInRom(true);
}else{
//手机外存储设备
appInfo.setInRom(false);
}
appInfo.setPackname(packname);
appInfo.setIcon(icon);
appInfo.setName(name);
appInfos.add(appInfo);
}
return appInfos;
}
}
三、建立一个实体类
package com.example.Darkbutton.Appmanager;
import android.graphics.drawable.Drawable;
/**
* @author xiaoxin007
* 2014-12-6下午5:37:47
* TODO 应用程序信息的业务bean
*/
public class AppInfo {
private Drawable icon;
private String name;
private String packname;
private boolean inRom;
private boolean userApp;
public Drawable getIcon() {
return icon;
}
public void setIcon(Drawable icon) {
this.icon = icon;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackname() {
return packname;
}
public void setPackname(String packname) {
this.packname = packname;
}
public boolean isInRom() {
return inRom;
}
public void setInRom(boolean inRom) {
this.inRom = inRom;
}
public boolean isUserApp() {
return userApp;
}
public void setUserApp(boolean userApp) {
this.userApp = userApp;
}
@Override
public String toString() {
return "AppInfo [name=" + name + ", packname=" + packname + ", inRom="
+ inRom + ", userApp=" + userApp + "]";
}
}
③ 主界面的业务逻辑
其实主要逻辑也无非是初始化组件,初始化数据,然后给listview 填充数据,最难的也就是adapter里面的逻辑
0.获取某个目录的空间大小
/**
* 获取某个目录的可用空间
*
* @param path
* @return
*/
private long getAvailSpace(String path) {
StatFs statf = new StatFs(path);
statf.getBlockCount();// 获取分区的个数
long size = statf.getBlockSize();// 获取分区的大小
long count = statf.getAvailableBlocks();// 获取可用的区块的个数
return size * count;
}
一,初始化组件
/**
* 初始化组件
*/
private void initView() {
tv_status = (TextView) findViewById(R.id.tv_status);
tv_avail_rom = (TextView) findViewById(R.id.tv_avail_rom);
tv_avail_sd = (TextView) findViewById(R.id.tv_avail_sd);
lv_app_manager = (ListView) findViewById(R.id.lv_app_manager);
ll_loading = (LinearLayout) findViewById(R.id.ll_loading);
}
二,初始化数据
/**
* 初始化数据
*/
private void initData() {
sdsize = getAvailSpace(Environment.getExternalStorageDirectory()
.getAbsolutePath());
romsize = getAvailSpace(Environment.getDataDirectory()
.getAbsolutePath());
tv_avail_sd
.setText("SD卡可用空间:" + Formatter.formatFileSize(this, sdsize));
tv_avail_rom.setText("内存可用空间:"
+ Formatter.formatFileSize(this, romsize));
}
三,给listview加入动画
/**
* listview动画
*/
private void initAnim() {
AnimationSet set = new AnimationSet(false);
Animation animation = new TranslateAnimation(1, 13, 10, 50); //ScaleAnimation 控制尺寸伸缩的动画效果
animation.setDuration(300);
set.addAnimation(animation);
LayoutAnimationController controller = new LayoutAnimationController(set, 1);
lv_app_manager.setLayoutAnimation(controller); //ListView 设置动画效果
}
四,给Listview填充数据
/**
* 给Listview填充数据
*/
private void fillDataToListView() {
//1.用户体验,加入progressbar
ll_loading.setVisibility(View.VISIBLE);
//2.耗时操作加入线程以免GG
new Thread() {
public void run() {
//3.调用 类,获取到软件信息
appInfos = AppInfoProvider.getAppInfos(AppManagerActivity.this);
//4.因为要把系统,用户软件分开,所以单独建立两个数据存储
userAppInfos = new ArrayList<AppInfo>();
systemAppInfos = new ArrayList<AppInfo>();
//5.遍历 填充进数组
for (AppInfo info : appInfos) {
if (info.isUserApp()) {
userAppInfos.add(info);
} else {
systemAppInfos.add(info);
}
}
// 加载listview的数据适配器 因为在线程之中,所以使用runOnUiThread 可以在ui更新
runOnUiThread(new Runnable() {
@Override
public void run() {
if (adapter == null) {
adapter = new AppManagerAdapter();
lv_app_manager.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
ll_loading.setVisibility(View.INVISIBLE);
}
});
};
}.start();
}
5.复杂的listview布局是怎么来的
private class AppManagerAdapter extends BaseAdapter {
// 控制listview有多少个条目 第一个1 代表是显示 用户应用 第二个1代表系统应用
@Override
public int getCount() {
return userAppInfos.size() + 1 + systemAppInfos.size() + 1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
AppInfo appInfo;
if (position == 0) {// 显示的是用程序有多少个的小标签
TextView tv = new TextView(getApplicationContext());
tv.setTextColor(Color.WHITE);
tv.setBackgroundColor(Color.GRAY);
tv.setText("用户程序:" + userAppInfos.size() + "个");
return tv;
} else if (position == (userAppInfos.size() + 1)) {
TextView tv = new TextView(getApplicationContext());
tv.setTextColor(Color.WHITE);
tv.setBackgroundColor(Color.GRAY);
tv.setText("系统程序:" + systemAppInfos.size() + "个");
return tv;
} else if (position <= userAppInfos.size()) {// 用户程序
int newposition = position - 1;// 因为多了一个textview的文本占用了位置
appInfo = userAppInfos.get(newposition);
} else {// 系统程序
int newposition = position - 1 - userAppInfos.size() - 1;
appInfo = systemAppInfos.get(newposition);
}
View view;
ViewHolder holder;
// if(position<userAppInfos.size()){//这些位置是留个用户程序显示的。
// appInfo = userAppInfos.get(position);
// }else{//这些位置是留个系统程序的。
// int newposition = position - userAppInfos.size();
// appInfo = systemAppInfos.get(newposition);
// }
if (convertView != null && convertView instanceof RelativeLayout) {
// 不仅需要检查是否为空,还要判断是否是合适的类型去复用
view = convertView;
holder = (ViewHolder) view.getTag();
} else {
view = View.inflate(getApplicationContext(),
R.layout.list_item_appinfo, null);
holder = new ViewHolder();
holder.iv_icon = (ImageView) view
.findViewById(R.id.iv_app_icon);
holder.tv_location = (TextView) view
.findViewById(R.id.tv_app_location);
holder.tv_name = (TextView) view.findViewById(R.id.tv_app_name);
view.setTag(holder);
}
holder.iv_icon.setImageDrawable(appInfo.getIcon());
holder.tv_name.setText(appInfo.getName());
if (appInfo.isInRom()) {
holder.tv_location.setText("手机内存");
} else {
holder.tv_location.setText("外部存储");
}
return view;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
④ 软件管理的功能实现
当点击 listview条目的时候,会出现一个popwindow 有卸载 有分享,有启动
/**
* 设置listview的点击事件
*/
lv_app_manager.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//设置点击第一个条目的时候不显示,因为不是软件
if (position == 0) {
return;
//以此类推
} else if (position == (userAppInfos.size() + 1)) {
return;
} else if (position <= userAppInfos.size()) {// 用户程序
int newposition = position - 1;
appInfo = userAppInfos.get(newposition);
} else {// 系统程序
int newposition = position - 1 - userAppInfos.size() - 1;
appInfo = systemAppInfos.get(newposition);
}
// System.out.println(appInfo.getPackname());
dismissPopupWindow();
//填充一个popwindow
View contentView = View.inflate(getApplicationContext(),
R.layout.popup_app_item, null);
ll_start = (LinearLayout) contentView
.findViewById(R.id.ll_start);
ll_share = (LinearLayout) contentView
.findViewById(R.id.ll_share);
ll_uninstall = (LinearLayout) contentView
.findViewById(R.id.ll_uninstall);
//启动的监听
ll_start.setOnClickListener(AppManagerActivity.this);
//分享的监听
ll_share.setOnClickListener(AppManagerActivity.this);
//卸载的监听
ll_uninstall.setOnClickListener(AppManagerActivity.this);
popupWindow = new PopupWindow(contentView, -2, -2);
// 动画效果的播放必须要求窗体有背景颜色。
// 透明颜色也是颜色
popupWindow.setBackgroundDrawable(new ColorDrawable(
Color.TRANSPARENT));
int[] location = new int[2];
view.getLocationInWindow(location);
// 在代码里面设置的宽高值 都是像素。---》dip
int dip = 60;
int px = DensityUtil.dip2px(getApplicationContext(), dip);
System.out.println("px=" + px);
popupWindow.showAtLocation(parent, Gravity.LEFT | Gravity.TOP,
px, location[1]);
ScaleAnimation sa = new ScaleAnimation(0.3f, 1.0f, 0.3f, 1.0f,
Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(300);
AlphaAnimation aa = new AlphaAnimation(0.5f, 1.0f);
aa.setDuration(300);
AnimationSet set = new AnimationSet(false);
set.addAnimation(aa);
set.addAnimation(sa);
contentView.startAnimation(set);
}
});
}
具体功能的实现
一,点击事件的处理
/**
* 布局对应的点击事件
*/
@Override
public void onClick(View v) {
dismissPopupWindow();
switch (v.getId()) {
case R.id.ll_share:
shareApplication();
break;
case R.id.ll_start:
startApplication();
break;
case R.id.ll_uninstall:
if (appInfo.isUserApp()) {
uninstallAppliation();
}else{
Toast.makeText(this, "系统应用只有获取root权限才可以卸载", 0).show();
//Runtime.getRuntime().exec("");
}
break;
}
}
二,用短信实现分享功能
/**
* 分享一个应用程序
*/
private void shareApplication() {
// Intent { act=android.intent.action.SEND typ=text/plain flg=0x3000000 cmp=com.android.mms/.ui.ComposeMessageActivity (has extras) } from pid 256
Intent intent = new Intent();
intent.setAction("android.intent.action.SEND");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "推荐您使用一款软件,名称叫:"+appInfo.getName());
startActivity(intent);
}
三 ,卸载应用
/**
* 卸载应用
*/
private void uninstallAppliation() {
// <action android:name="android.intent.action.VIEW" />
// <action android:name="android.intent.action.DELETE" />
// <category android:name="android.intent.category.DEFAULT" />
// <data android:scheme="package" />
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.setAction("android.intent.action.DELETE");
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("package:" + appInfo.getPackname()));
startActivityForResult(intent, 0);
}
四 ,开启一个应用程序
/**
* 开启一个应用程序
*/
private void startApplication() {
// 查询这个应用程序的入口activity。 把他开启起来。
PackageManager pm = getPackageManager();
// Intent intent = new Intent();
// intent.setAction("android.intent.action.MAIN");
// intent.addCategory("android.intent.category.LAUNCHER");
// //查询出来了所有的手机上具有启动能力的activity。
// List<ResolveInfo> infos = pm.queryIntentActivities(intent,
// PackageManager.GET_INTENT_FILTERS);
Intent intent = pm.getLaunchIntentForPackage(appInfo.getPackname());
if (intent != null) {
startActivity(intent);
} else {
Toast.makeText(this, "不能启动当前应用", 0).show();
}
}
点击下载源码