当前位置:  编程技术>移动开发
本页文章导读:
    ▪Bit地图 详解(1)- 提高Bit地图解析速度( Resources , Bit地图Factory , AssetManager ,主题定制 )        Bitmap 详解(1)- 提高Bitmap解析速度( Resources , BitmapFactory , AssetManager ,主题定制 )       图片是应用里面最常用的资源,在canvas里面使用需要将其解析成Bitmap的方式(例如倒影效果)。这里.........
    ▪ 动态增添view        动态添加view 前面说的都是用的Interface Builder来编辑.xib文件来给窗口添加各种控件以及给控件绑定数据(IBOutlet)、关联事件响应函数(IBAction)。 这章学习的是动态的添加view,不使用Interface Builde.........
    ▪ 统计索引大小和时间删除早期的大文件       统计目录大小和时间删除早期的大文件 为什么要做这些,等你需要的时候你就知道了 private void deleteOldestFile(File directory) { File[] files = directory.listFiles(); Arrays.sort(files, new Comparator<File>() { .........

[1]Bit地图 详解(1)- 提高Bit地图解析速度( Resources , Bit地图Factory , AssetManager ,主题定制 )
    来源: 互联网  发布时间: 2014-02-18
Bitmap 详解(1)- 提高Bitmap解析速度( Resources , BitmapFactory , AssetManager ,主题定制 )

      图片是应用里面最常用的资源,在canvas里面使用需要将其解析成Bitmap的方式(例如倒影效果)。这里给出几个可能会有的场景,探讨一下如何使用:

  • 应用主题转化:当某个应用希望换掉整个生命周期中的一些背景图片,例如从卡通主题转化到草原主题,这样会涉及到Button、Tab、Layout等各式各样图片的替换。
  • 动画播放:例如关机动画、闹铃提醒(当然简单的动作除外)

      转载请注明http://ishelf.iteye.com/blog/1032563

      场景一中,可以通过apk升级来实现,也可以通过调用外部资源来实现。这两种方式比较简单,问题也就显而易见。第一种apk升级很烦人,至少我自己都懒得去。第二种,外部资源是简单,不过图片的解析速度一定会比从apk中调用drawable资源要慢好几倍,对于配置很好的机器这个速度不是问题,可是中下的机器可就够受了(最近试了试中兴的平板,和三星的对比太鲜明了)。这两个的前提都是对图片显示要求不是非常的很高,例如图片预览

      在场景二中,需要考虑到定制的问题。你给国内和国外的关机动画不能一样吧,给联通和给电信定制的不能一样吧(这个也根据需求而定,不排除都一样的可能)。这样当需求变化时,难道你的代码也要跟着变化么? 这样的话真给Java显眼了,O(∩_∩)O。 其实在场景一中的主题替换也是一个定制的问题。

      如何能在保证即不修改代码又能保证图片解析速度尽可能快的前提下,做到图片资源的定制是接下来要讨论的问题。首先看代码

 

 

orginalbm = BitmapFactory.decodeFile(Path);
//解析源图片文件,根据需要可以放在任何地方。

orginalbm = BitmapFactory.decodeResource(resources,source_id);
//解析apk中的资源图片。可以放置到一个不包含任何Java文件的apk包中去。
 

 

      第二种方式一定是比第一种方式速度快(大家有什么异议可以讨论一下)。接下来就是如何用apk解析的方式来动态的加载外部的图片资源(也可以包括Layout,anim和xml资源)。

 

     第一步就是解决如何解析apk包,并将资源加载进来。这要分两种情况:一是在应用中使用,而是在framework框架中。

 

 

这样也就有两种方式,首先介绍第一种,直接看代码

 

		try {
			// apk包的文件路径
			// 这是一个Package 解释器, 是隐藏的
			// 构造函数的参数只有一个, apk文件的路径
			// PackageParser packageParser = new PackageParser(apkPath);
			Class pkgParserCls = Class.forName(PATH_PackageParser);
			Class[] typeArgs = new Class[1];
			typeArgs[0] = String.class;
			Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs);
			Object[] valueArgs = new Object[1];
			valueArgs[0] = apkPath;
			Object pkgParser = pkgParserCt.newInstance(valueArgs);
			Log.d("ANDROID_LAB", "pkgParser:" + pkgParser.toString());
			// 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
			DisplayMetrics metrics = new DisplayMetrics();
			metrics.setToDefaults();
			// PackageParser.Package mPkgInfo = packageParser.parsePackage(new
			// File(apkPath), apkPath,
			// metrics, 0);
			typeArgs = new Class[4];
			typeArgs[0] = File.class;
			typeArgs[1] = String.class;
			typeArgs[2] = DisplayMetrics.class;
			typeArgs[3] = Integer.TYPE;
			Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod(
					"parsePackage", typeArgs);
			valueArgs = new Object[4];
			valueArgs[0] = new File(apkPath);
			valueArgs[1] = apkPath;
			valueArgs[2] = metrics;
			valueArgs[3] = 0;
			Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser,
					valueArgs);
			// 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
			// ApplicationInfo info = mPkgInfo.applicationInfo;
			Field appInfoFld = pkgParserPkg.getClass().getDeclaredField(
					"applicationInfo");
			ApplicationInfo info = (ApplicationInfo) appInfoFld
					.get(pkgParserPkg);
			// uid 输出为"-1",原因是未安装,系统未分配其Uid。
			Log.d("ANDROID_LAB", "pkg:" + info.packageName + " uid=" + info.uid);
			Class assetMagCls = Class.forName(PATH_AssetManager);
			Constructor assetMagCt = assetMagCls.getConstructor((Class[]) null);
			Object assetMag = assetMagCt.newInstance((Object[]) null);
			typeArgs = new Class[1];
			typeArgs[0] = String.class;
			Method assetMag_addAssetPathMtd = assetMagCls.getDeclaredMethod(
					"addAssetPath", typeArgs);
			valueArgs = new Object[1];
			valueArgs[0] = apkPath;
			assetMag_addAssetPathMtd.invoke(assetMag, valueArgs);
			Resources res = getResources();
			typeArgs = new Class[3];
			typeArgs[0] = assetMag.getClass();
			typeArgs[1] = res.getDisplayMetrics().getClass();
			typeArgs[2] = res.getConfiguration().getClass();
			Constructor resCt = Resources.class.getConstructor(typeArgs);
			valueArgs = new Object[3];
			valueArgs[0] = assetMag;
			valueArgs[1] = res.getDisplayMetrics();
			valueArgs[2] = res.getConfiguration();
			res = (Resources) resCt.newInstance(valueArgs);

       代码是参考来源:http://blog.csdn.net/sodino/archive/2011/03/01/6215224.aspx    。这里主要使用了Java反射机制,得到了res(Resources)(这个博主挺nb的,O(∩_∩)O)。 Resources类是实现apk资源解码的核心,具体类的作用这里就不介绍了(不懂得看源码去)。

       如果是在framework中使用就简单了,看代码

 

        AssetManager assets = new AssetManager();
        String resDir = "/sdcard/extern-sd/xxx.apk";
        if (assets.addAssetPath(resDir) == 0) {
            Log.e(TAG, "parse failed");
            return;
        }
        resources = new Resources(assets, null, null, null);

        这样很简单就得到了Resources类。

 

     第二步是解决如何得到drawble资源的id值。这里我们根据需要为每个drawable添加相应的参数,例如在哪个类里面使用、名称等各种信息。

       先看代码:

 

 

		int all_view_id = resources.getIdentifier("image_ids", "xml",
				"com.xxx.resource");
		XmlResourceParser parser = resources.getXml(all_view_id);
		try {
			int type;
			while ((type = parser.next()) != XmlPullParser.START_TAG
					&& type != XmlPullParser.END_DOCUMENT) {;}

			if (type != XmlPullParser.START_TAG) {
				Log.e(TAG, "No start tag found in package manager 	settings");
			}
			int outerDepth = parser.getDepth();
			while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
					&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
				if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
					continue;
				}
				String tagName = parser.getName();
			}
		} catch (XmlPullParserException e) {
			Log.e(TAG, "Error reading package manager settings", e);
		} catch (java.io.IOException e) {
			Log.e(TAG, "Error reading package manager settings", e);
		}

 

      通过getIdentifier可以得到需要的xml文件id值。

 

 resources.getIdentifier("image_ids", "layout","com.xxx.resource");

 

     //字段“layout”,表示资源文件在layout文件夹中

     //字段“com.xxx.resource”表示该apk的包名(packagename)

     需要注意一点在自己配置的xml文件中,要使用android:drawable这样的属性名定义,否则不会编译成int类型的id号。

 


     最后一步就是如何调用通过id调用图片。

 

BitmapFactory.decodeResource(resources, source_id);

     resources就是第一步得到的Resources类,id则是第二部得到的id号。需要注意一点就是变量的作用域。

 

 

经过上面三步可以很容易的实现使用apk的方式调用外部的图片资源。

 

 

 

 

 

 

 

 

 

 

 

 

 


    
[2] 动态增添view
    来源: 互联网  发布时间: 2014-02-18
动态添加view

前面说的都是用的Interface Builder来编辑.xib文件来给窗口添加各种控件以及给控件绑定数据(IBOutlet)、关联事件响应函数(IBAction)。

这章学习的是动态的添加view,不使用Interface Builder。这里用label和button示例:

 

找到新建工程XXXViewController.m的-(void)loadView方法,去掉注释并添加如下代码

 

- (void)loadView {

//创建一个UIView 对象

UIView *view =

[[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];

view.backgroundColor = [UIColor lightGrayColor];

 

//创建一个label view

CGRect frame = CGRectMake(10, 15, 300, 20);

UILabel *label = [[UILabel alloc] initWithFrame:frame];

label.textAlignment = UITextAlignmentCenter;

label.backgroundColor = [UIColor clearColor];

label.font = [UIFont fontWithName:@”Verdana” size:20];

label.text = @”label test”;

label.tag = 1000;

 

//创建一个按钮view

frame = CGRectMake(10, 30, 300, 50);

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

button.frame = frame;

[button setTitle:@”button test” forState:UIControlStateNormal];

button.backgroundColor = [UIColor clearColor];

button.tag = 2000;

 

/*下面这个调用用C++的格式来看就是button->addTarget(this->action, @selector(buttonClicked:), UIControlEventTouchUpInside);

中间的action:以及forControlEvent:实际上都是函数签名的一部分。@selector(buttonClicked:) 相当于函数指针(一个冒号表明函数有一个参数),这里指向的是buttonClicked函数

也就是下面定义的按钮响应函数*/

[button addTarget:self action:@selector(buttonClicked:) forControlEvent:UIControlEventTouchUpInside];

[view addSubview:label];

[view addSubview:button];

self.view = view;

[label release];

}

 

在这个文件中添加按钮响应函数

-(IBAtion) buttonClicked:(id)sender {

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Action invoked”

message:@”button clicked”

delegate:self

cancelButtonTitle:”@ok”

otherButtonTitles:nil];

[alert show];

[alert release];

}

 

label的矩形区域是CGRectMake(10, 15, 300, 20); 既左上角坐标是10,15宽度高度分别是300, 20.

button的矩形区域的左上角坐标是10, 30 ,它们有重叠的地方。

这里遮挡是后加到view里面去的遮挡先加进去的。所以button遮挡了label。可以通过

[view exchangeSubviewAtIndex:1 withSubviewAtIndex:0];

来修改遮挡。我的理解是view按照控件加进去的顺给了个index,这个index从0开始递增。显示的时候index数值较大控件遮挡数值较小的。 上面这个函数交换了最先加进去的两个控件(实际上只有这两个)的index


    
[3] 统计索引大小和时间删除早期的大文件
    来源: 互联网  发布时间: 2014-02-18
统计目录大小和时间删除早期的大文件

为什么要做这些,等你需要的时候你就知道了

private void deleteOldestFile(File directory)
{
File[] files = directory.listFiles();
Arrays.sort(files, new Comparator<File>() { 
    @Override
    public int compare(File f1, File f2) 
    {       
        return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());        
    }});

files[0].delete();
 }

private static long dirSize(File dir) {
long result = 0;
File[] fileList = dir.listFiles();

for(int i = 0; i < fileList.length; i++) {

    if(fileList[i].isDirectory()) {
        result += dirSize(fileList [i]);
    } else {
        // Sum the file size in bytes
        result += fileList[i].length();
    }
 }
return result; 
}

File dirlist = new File(Environment.getExternalStorageDirectory() + "/VideoList");

if(!(dirlist.exists()))
dirlist.mkdir();

Long directorySize = dirSize(dirlist);

 if (directorySize > 1073741824) // this is 1GB in bytes
 {
    deleteOldestFile(dirlist); 
 }

File TempFile = new File(Environment.getExternalStorageDirectory() 
                + "/VideoList", dateFormat.format(date) + fileFormat);
mediaRecorder.setOutputFile(TempFile.getPath());
或者
while (directorySize > 1073741824)
{
  deleteOldestFile(dirlist);
  direcotrySize = dirSize(dirlist);
}



    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3