《Android羣英傳》讀書筆記(10)第九章:Android系統信息與安全機制

  1. Android系統信息獲取

獲取系統信息的途徑,有下面兩種途徑:

  • android.os.Build
  • SystemProperty
android.os.Build類裏面的信息非常豐富,它包含了系統編譯時的大量設備、配置信息,下面列舉了一些:

  • Build.BOARD——主板
  • Build.BRAND——Android系統定製商
  • Build.SUPPORTED_ABIS——CPU指令集
  • Build.DEVICE——設備參數
  • Build.DISPLAY——顯示屏參數
  • Build.FINGERPRINT——唯一編號
  • Build.SERIAL——硬件序列號
  • Build.ID——修訂版本列表
  • Build.MANUFACTURER——硬件製造商
  • Build.MODEL——版本
  • Build.HARDWARE——硬件名
  • Build.PRODUCT——手機產品名
  • Build.TAGS——描述Build的標籤
  • Build.TYPE——Builder類型
  • Build.VERSION.CODENAME——當前開發代號
  • Build.VERSION.INCREMENTAL——源碼控制版本號
  • Build.VERSION.RELEASE——版本字符串
  • Build.VERSION.SDK_INT——版本號
  • Build.HOST——host值
  • Build.USER——User名
  • Build.TIME——編譯時間
下面來看一下SystemProperty裏的常用參數,可以通過System.getProperty:

  • os.version——OS版本
  • os.name——OS名稱
  • os.arch——OS架構
  • user.home——home屬性
  • user.name——name屬性
  • user.dir——Dir屬性
  • user.timezone——時區
  • path.separator——路徑分隔符
  • line.separator——行分隔符
  • file.separator——文件分隔符
  • java.vendor.url——Java vender Url屬性
  • java.class.path——Java Class屬性
  • java.class.version——Java Class版本
  • java.vendor——Java Vender屬性
  • java.version——Java版本
  • java.home——Java Home屬性

2.PackageManager

Android提供了PackageManager來負責管理所有已安裝的App,PackageManager可以獲得AndroidManifest中不同節點的封裝信息,下面是一些常用的封裝信息:
  • ActivityInfo
ActivityInfo封裝在了Mainfest文件中的<activity></activity>和<receiver></receiver>之間的所有信息,包括name、icon、label、launchMode等。
  • ServiceInfo
ServiceInfo與ActivityInfo類似,封裝了<service></service>之間的所有信息。
  • ApplicationInfo
它封裝了<application></application>之間的信息,特別的是,ApplicationInfo包含了很多Flag,FLAG_SYSTEM表示爲系統應用,FLAG_EXTERNAL_STORAGE表示爲安裝在SDcard上的應用,通過這些flag可以很方便的判斷應用的類型。
  • PackageInfo
PackageInfo包含了所有的Activity和Service信息。
  • ResolveInfo
ResolveInfo包含了<intent>信息的上級信息,所以它可以返回ActivityInfo、ServiceInfo等包含了<intent>的信息,經常用來幫助找到那些包含特定intent條件的信息,如帶分享功能、播放功能的應用。
有了這些封裝的信息後,還需要有特定的方法來獲取它們,下面就是PackageManager中封裝的用來獲取這些信息的方法:
  • getPackageManager()——通過這個方法可以返回一個PackageManager對象。
  • getApplicationInfo()——以ApplicationInfo的形式返回指定包名的ApplicationInfo。
  • getApplicationIcon()——返回指定包名的Icon。
  • getInstalledApplications()——以ApplicationInfo的形式返回安裝的應用。
  • getInstalledPackages()——以PackageInfo的形式返回安裝的應用。
  • queryIntentActivities()——返回指定Intent的ResolveInfo對象、Activity集合。
  • queryIntentServices()——返回指定Intent的ResolveInfo對象、Service集合。
  • resolveActivity()——返回指定Intent的Activity。
  • resolveService()——返回指定Intent的Service。
根據ApplicationInfo的flag來判斷App的類型:
如果當前應用的flags & ApplicationInfo.FLAG_SYSTEM != 0則爲系統應用
如果flags & ApplicationInfo.FLAG_SYSTEM <= 0 則爲第三方應用
特殊的當系統應用升級後也會成爲第三方應用,此時 flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP != 0;
如果flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0 則爲安裝在SDCard上的應用。

下面是一個列出手機上安裝的所有App的示例:
public class PkgMgr extends AppCompatActivity implements View.OnClickListener {
    private PackageManager mPackageManager;

    private ListView mList;
    private PkgAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pkg_mgr);
        mPackageManager = getPackageManager();
        mList = (ListView) findViewById(R.id.list);
        mAdapter = new PkgAdapter(this);
        mList.setEmptyView(findViewById(R.id.empty));
        mList.setAdapter(mAdapter);
        findViewById(R.id.btn_all).setOnClickListener(this);
        findViewById(R.id.btn_third).setOnClickListener(this);
        findViewById(R.id.btn_system).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {

        List<AppInfo> result;
        switch (v.getId()) {
            case R.id.btn_all:
                result = getAppInfo(R.id.btn_all);
                break;
            case R.id.btn_third:
                result = getAppInfo(R.id.btn_third);
                break;
            case R.id.btn_system:
                result = getAppInfo(R.id.btn_system);
                break;
            default:
                result = new ArrayList<>();
        }
        mAdapter.addAll(result);
    }

    private List<AppInfo> getAppInfo(int flag) {
        List<ApplicationInfo> appInfos = mPackageManager.getInstalledApplications(
                PackageManager.GET_UNINSTALLED_PACKAGES);
        List<AppInfo> list = new ArrayList<>();
        //根據不同的flag來切換顯示不同的App類型
        switch (flag) {
            case R.id.btn_all:
                list.clear();
                for (ApplicationInfo appInfo : appInfos) {
                    list.add(makeAppInfo(appInfo));
                }

                break;
            case R.id.btn_third:
                list.clear();
                for (ApplicationInfo appInfo : appInfos) {
                    if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
                        list.add(makeAppInfo(appInfo));
                    } else if ((appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0){
                        list.add(makeAppInfo(appInfo));
                    }
                }
                break;
            case R.id.btn_system:
                list.clear();
                for (ApplicationInfo appInfo : appInfos) {
                    if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        list.add(makeAppInfo(appInfo));
                    }
                }
                break;
        }
        return list;
    }

    private AppInfo makeAppInfo(ApplicationInfo appInfo) {
        AppInfo info = new AppInfo();
        info.setAppIcon(appInfo.loadIcon(mPackageManager));
        info.setAppLabel(appInfo.loadLabel(mPackageManager).toString());
        info.setPkgName(appInfo.packageName);
        return info;
    }

}
下面是Adapter類:
public class PkgAdapter extends BaseAdapter {

    private Context mContext;
    private List<AppInfo> mList;
    public PkgAdapter(Context context) {
        mContext = context;
        mList = new ArrayList<>();
    }

    public void addAll(List<AppInfo> list) {
        mList.clear();
        mList.addAll(list);
        notifyDataSetChanged();
    }
    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public AppInfo getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        AppInfo item = getItem(position);
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_app_info, parent, false);
            holder.mIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
            holder.mLabel = (TextView) convertView.findViewById(R.id.tv_label);
            holder.mPkgName = (TextView) convertView.findViewById(R.id.tv_pkg_name);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.mIcon.setImageDrawable(item.getAppIcon());
        holder.mLabel.setText(item.getAppLabel());
        holder.mPkgName.setText(item.getPkgName());
        return convertView;
    }

    static class ViewHolder{
        ImageView mIcon;
        TextView mLabel;
        TextView mPkgName;
    }
}

AppInfo 類,將獲得的ApplicationInfo進一步封裝,在ListView中顯示:
public class AppInfo {

    private String appLabel;
    private String pkgName;
    private Drawable appIcon;

    public String getAppLabel() {
        return appLabel;
    }

    public void setAppLabel(String appLabel) {
        this.appLabel = appLabel;
    }

    public String getPkgName() {
        return pkgName;
    }

    public void setPkgName(String pkgName) {
        this.pkgName = pkgName;
    }

    public Drawable getAppIcon() {
        return appIcon;
    }

    public void setAppIcon(Drawable appIcon) {
        this.appIcon = appIcon;
    }
}
下面是運行效果:

3.ActivityManager

與PackageManager不同,ActivityManager側重於獲取正在運行的應用程序信息,可以通過context.getSystemService(Context.ACTIVITY_SERVICE);來獲得。下面是這個類中封裝的一些信息:
  • ActivityManager.MemoryInfo——MemoryInfo有幾個非常重要的字段:availMem(系統可用內存),totalMem(總內存),threshold(低內存的閾值,即區分是否低內存的臨界值),lowMemory(是否處於低內存)。
  • Debug.MemoryInfo——這個MemoryInfo用於統計進程下的內存信息。
  • RunningAppProcessInfo——運行進程的信息,存儲的字段有:processName(進程名),pid(進程pid),uid(進程uid),pkgList(該進程下的所有包)
  • RunningServiceInfo——運行的服務信息,在它裏面同樣包含了一些服務進程信息,同時還有一些其他信息。activeSince(第一次被激活的時間、方式),foreground(服務是否在後臺執行)。
下面是使用ActivityManager獲取運行的進程信息的示例:
public class  AtyMgr extends AppCompatActivity{
    private ActivityManager am;

    private ListView mList;

    private AtyAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aty_mgr);
        am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        mList = (ListView) findViewById(R.id.aty_list);
        mAdapter = new AtyAdapter(this,getRunningProcessInfo());
        mList.setAdapter(mAdapter);
    }

    private List<AtyInfo> getRunningProcessInfo() {
        List<ActivityManager.RunningAppProcessInfo> processInfoList;
        processInfoList = am.getRunningAppProcesses();
        List<AtyInfo> result = new ArrayList<>();
        Log.d("TAG", "size = " + processInfoList.size());
        for (ActivityManager.RunningAppProcessInfo processInfo : processInfoList) {
            result.add(makeProcessInfo(processInfo));
        }
        return result;
    }

    private AtyInfo makeProcessInfo(ActivityManager.RunningAppProcessInfo processInfo) {
        AtyInfo atyInfo = new AtyInfo();
        atyInfo.setPid(processInfo.pid + "");
        atyInfo.setUid(processInfo.uid + "");
        Debug.MemoryInfo[] memoryInfos = am.getProcessMemoryInfo(new int[]{processInfo.pid});
        int memorySize = memoryInfos[0].getTotalPss();
        atyInfo.setMemory(memorySize);
        atyInfo.setProcessName(processInfo.processName);
        return atyInfo;
    }

}
Adapter的代碼與上面PackageManager示例類似,不再貼出來了。

發佈了34 篇原創文章 · 獲贊 2 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章