练手小项目(5)安全卫士_软件管理器

还是继续复习我的安卓基础吧,毕竟基础才是最重要的

这一篇文章将会用到复杂的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();
		}
	}

点击下载源码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值