关于最近找工作

这些天发生了很多事情。。。。

一直以为,自己能够去BAT之类的企业,可是,在经历过网上投递的简历的过程,没有一家曾经一直看好的大型企业给我回电。包括小米,果壳网,douban,金山,华为,联想等等, 个中滋味谁能懂?我也在反思。既然不能选择好的企业,那就选择自己想去的城市,在微信上看到eebbk的现场面试,我想都没多想,22号开题答辩完,第二天我就坐高铁赶到深圳,租了一个床位,20元一天,就开始了找工作之旅。

首先安顿好后,我借助百度地图来到了eebbk的面试地点。在填了一些表格,提交简历之后,在一个房间等候了一段时间,然后就是和技术面,技术面问了我很多关于android的知识,问我有没有android中间件的开发,我当然没有相关的开发经验,结果没戏。晚上回到宿舍,有一家叫盒子支付的创业公司邀我面试,过去做了下笔试题,感觉做得并不好,不过和技术经理面谈停愉快得。也过了,不过是作为实习岗去的,月薪是2k,可以包住。一开始,真的接受不了,2k的工资在这边租房都不够,不过看到移动支付的行业我觉得是有前景的,也就答应了,但10天内给他答复具体的时间,顺便看一下其他的工作机会,晚上在网上看到27号有人才招聘会。

第三天,杨怀林就过来了,原本他是准备和我一道过来的,但是不晓得他有什么事情,就退掉了,他过来在网上投的简历也一个电话也没有回。上午去了ob哥那儿玩了下,下午我们又去了一趟,深圳湾,其实在前一天我也去过,一个人去的,在车上我想了很多,为什么要来这座城市,是工资或者是小时候他没有带我过来?都不是,是海和风。我喜欢这里的环境,不似长沙那样酷热或寒冷,也不似北京那样干燥和地域歧视。

第四天,我和杨怀林去参加了深圳人才市场的招聘会。人很多,几家招聘android的公司我都去面试了,结果都让我去复试,其实在那儿招聘的公司大都不怎么样。我就选择了南山区的一家叫做海泰康的公司,和我们一起竞争的人也有很多,我由于去参加一个小笔试去了,只有怀林参加了他们的笔试,他电话叫我下去帮他做题目,我也就下去了,其实当时我已经准备去盒子支付了的。但是被杨怀林一怂恿就去参加海泰康的面试了,他们之前是一家做芯片,微处理器的公司,现在准备在智能盒子方面发力,主要是面向低层嵌入式的。这也是我做android需要加强的地方,上层应用我觉得没什么太大问题,但对于android框架我其实并不熟悉,也想学习一下底层的东西。抱着这个想法我去了那家公司面试,面试结果很顺利。也答应录用,我当时也一直在犹豫是去盒子支付还是在这里,后来这边给我提供的工资是3.5k ,包住宿。相比优势就明显了。后来我打电话给盛哥(盒子支付面我的那个),把想法告诉了他,其实如果盒子支付能够稍微给我涨点工资,我大概也就还是会选责盒子,毕竟是第一家能看上我(也是我能够看上的公司),盛哥说帮我问问人事,再回复,估计后来没戏了。

再说说住宿吧,住在这里有大6天了,这里都是20出头刚出来找工作的人,大部分是高中毕业后学习一门技术谋生的,虽然不知道对方名字,但相处的还算融洽,有一个高中毕业后去培训了3个月的游戏开发,现在从事flash游戏,其实他对技术是很着迷的那类,每天看他不是知乎就是csdn,我都没有他逛得多,也关注流行技术和框架,我再想要是当初我没考上大学也会不会是这样呢。还有一个大学生,胖胖的,在我隔壁床的下床,做的是物流专业,每周工作6天,目前工作1年了,我的下床是一个厨师,每天起得很晚,而最奇葩得是我隔壁床上铺,他好像没什么正式工作,看他有时在看一本宝石鉴定方面得书。哦 还有一个搞.net的 ,一个做通讯行业的,我们这个房间一共8个人。隔壁房间貌似还有一个程序员,应该是做java的,目前也是在找工作,上次去晾衣服路过,居然听他在全英文电话面试,顿时觉得自己。。总之这是一个鱼龙混杂的地方,也是让我初次接触到社会的残酷。

利用java反射机制实现对象值拷贝

首先需求是这样的 ,我把它简化一下:

User user1=new User();
user1.setUserName("wxn");
User user2=new User();
user2.setUserName("kkkk");
User user3=user2;

接下来的操作我想让user2中的值和user1中的值全部相等。我们知道可以通过 user2=user1.clone()方法去获得一个新的对象,这种方法的详细介绍在这里可以学习。http://www.cnblogs.com/yxnchinahlj/archive/2010/09/20/1831615.html

但是这样clone出来的是一个新的对象,user2就是user1的一个新对象的拷贝,虽然user2中的值可以和user1中的值相等,但是 user3就已经不是user2之前的对象了,我需要user3中的值也跟着改变。

于是最简单的方法就是在User类中增加一个方法

public void copy(User user){
    this.setUserName(user.getUserName);
    this.setUserId(user.setUserId);
     .....
}

如果user中的属性太多怎么办?那写起来太麻烦了,除了方法名get和set有区别之外没什么区别, 于是我想起了之前看过的java反射机制来批量处理,顺便巩固一下java的反射机制,实现代码如下

public void copy(User user) {
//获得User类中所有的方法
		Method[] methods = user.getClass().getMethods();
		try {
		for (int i = 0; i < methods.length; i++) {
				String mName = methods[i].getName();
				if (mName.startsWith("set")) {
					String nName =null;
					//若为boolean的属性则没有get方法 只有 isXXX方法
					 if(boolean.class.equals(methods[i].getParameterTypes()[0]) ){
						  nName=mName.replace("set", "is");
					  }	else{
						  nName=mName.replace("set", "get");
					  }
					Method method = user.getClass().getDeclaredMethod(nName,
							null);
					methods[i].invoke(this, method.invoke(user, null));
				}

			} 
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

全部代码如下


import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 
 * @author ahsiu
 * 
 */

public class User {
	private int userId;
	private String userName;
	private String password;
	private String email;
	private String phone;
	private int loginState;
   private boolean flag;
	public int getUserId() {
		return userId;
	}

	public void copy(User user) {
		Method[] methods = user.getClass().getMethods();
		try {
			for (int i = 0; i < methods.length; i++) {
				String mName = methods[i].getName();
				if (mName.startsWith("set")) {

					String nName =null;
					//若为boolean的属性则没有get方法 只有 isXXX方法
					 if(boolean.class.equals(methods[i].getParameterTypes()[0]) ){
						  nName=mName.replace("set", "is");
					  }	else{
						  nName=mName.replace("set", "get");
					  }

					Method method = user.getClass().getDeclaredMethod(nName,
							null);
					methods[i].invoke(this, method.invoke(user, null));

				}

			}
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void setUserId(int userId) {
		this.userId = userId;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public int getLoginState() {
		return loginState;
	}

	public void setLoginState(int loginState) {
		this.loginState = loginState;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	public static void main(String[] args) {
		User user1=new User();
		user1.setUserName("wxn");
		User user2=new User();
		user2.setUserName("kkkk");
		User user3=user2;
		System.out.println(user1.getUserName());
		System.out.println(user2.getUserName());
		System.out.println(user3.getUserName());	
		System.out.println("");
		user2.copy(user1);
		System.out.println(user1.getUserName());
		System.out.println(user2.getUserName());
		System.out.println(user3.getUserName());
		System.out.println("");
		user3.setUserName("ahsiu");
		System.out.println(user1.getUserName());
		System.out.println(user2.getUserName());
		System.out.println(user3.getUserName());
	}
}

[转]android解决图片加载oom的方法

大家好,今天给大家分享的是解决解析图片的出现oom的问题,我们可以用BitmapFactory这里的各种Decode方法,如果图片很小的话,不会出现oom,但是当图片很大的时候

就要用BitmapFactory.Options这个东东了,Options里主要有两个参数比较重要.

options.inJustDecodeBounds = false/true;
//图片压缩比例.
options.inSampleSize = ssize;

我们去解析一个图片,如果太大,就会OOM,我们可以设置压缩比例inSampleSize,但是这个压缩比例设置多少就是个问题,所以我们解析图片可以分为俩个步骤,第一步就是获取图片的宽高,这里要设置Options.inJustDecodeBounds=true,这时候decode的bitmap为null,只是把图片的宽高放在Options里,然后第二步就是设置合适的压缩比例inSampleSize,这时候获得合适的Bitmap.这里我画了简单的流程图,如下:

继续阅读“[转]android解决图片加载oom的方法”

对现有云盘的一些想法

事情是这样的,我这个笔记本的ssd硬盘只有256G,虽然目前还够用,但难保我这种不善于整理文件的人来说,迟早会全部占满的, 于是我想通过网盘分担一部分的存储,于是想到了云盘,后来发现好像只有百度有mac版本的同步盘,下载安装后,在本地选择了一个目录作为同步目录,结果,它居然把网盘上所有的文件都同步下来了。这可不是我想要的。

我觉得云盘同步盘应该是像tortoise那样作为一个插件,可以直接对目录同步,微云的那个作为一个单独软件(mac版本)让用户上传下载,真心还是一个上个时代的产品,除了传大文件方便点,对于操作目录还是不够方便, 目前很多云盘提供的网络存储都是好几T的空间了,虽然自己个人资料加起来都没有几个T,个人电脑的硬盘也能够达到T级别,可是对于本地存储空间不大的ssd的笔记本,和移动设备还是需要更多的存储空间, 云盘服务提供的同步盘能够让用户感觉自己的资料放在本地,目前看的百度云盘的同步盘功能是在服务端和本地同时存了一份,如果换一台电脑,比如我到台式机上去,安装同步盘,用同一个帐号登陆,同样会把所有的文件同步下来,可是如果有好几个T的资料呢?我并不需要把所有的文件都同步下来,比如有很多视频资料可以在线播放,何必都要下载下来占本地的资源呢?我希望只在本地留一个镜像文件,如果要同步可以自己手动同步,也可以设置哪些文件或者目录一旦变更就自动同步,这一点对自己写的文档或者代码,可以在切换不同的电脑时感觉会很方便。

小手一抖,500溜走

最近发生很多破财事情,第一件就是我买了台macbook pro ,retina ,15寸,二手,花了将近1W大洋,还是透支着,从大姐那借了钱,答应毕业后找到工作自己挣钱了还。

为什么一定要买macbook?我也说不清,大概是一见钟情?看到retina的屏幕,再也无法直视其他电脑屏幕了,我那台黑苹果终于到了该退休的年龄。使用mac os x 真的比windows好太多,触摸板真的是天才的设计,但考虑到一些应用大概只有windows下面才方便,还是开了个虚拟机,装了个win7,在mac下跑虚拟机开win7 一点儿也不卡顿,三个手指一划随时切换两个系统。唯一让我觉得用的有点不爽的只能酸这个键盘了,特别是上下左右键,太小挨得太紧了。很容易误按。所以虽然花了大价钱,但是还是值得得,期待不要出现问题。

第二件破财的事情就是今天,起床,抖了下被子,手机哐当就掉地上了,也没多高,半米不到,屏幕居然碎了,碎了!上次在寝室从上铺床上掉下来一点事都没有,这次居然就碎了!还只怪自己太大意了,上网查了下换屏费用,500,靠,现在500都可以买视网膜新手机了,但是我很多资料都是在这个miui系统中,这个系统也一直是我最喜欢和习惯的系统,如果真的买个新的想必又得花费,思来想去还是准备换屏幕吧,毕竟还没过保修(这个自己屏幕当然不能保修),但是如果自己拆的话就完全不能保修了。所以,没考虑到网上采购屏幕自己换,其实看了网上自己换屏视屏,自己换也很简单,但正品原装屏幕也差不多要400,还是让售后换吧。

所以,这个学期得省,工作的事情还是没有着落,我现在真有点觉得不应该推掉那些工作的。要不然至少也有份收入吧。算了,后悔也没有用,我坚信,好的更加适合我的工作还在等着我呢,4级下周又要开始考试了,最后拼搏一把吧!

程序员浪费生命的几种方式

     程序员应该要爱惜生命,做有用有意义的事情。做有用的事情,有两种方式,一、做一个对用户真正有价值的项目,这个项目是真正有意义有用的;二、朝正确的方向以正确的方式做项目。但是程序员会遇到很多失败的项目,这些系统要么是没有人用没有真正价值,要么是以不正确的方式做项目,使用不当的技术,例如,用报表工具代替查询、用ESB企业总线当作海量数据传输用,或者做一些没有实际用途的功能,如做一个万能的用户自定义查询系统、做用户自定义工作流工具、做用户自定义报表工具,这些项目无疑在浪费程序员的生命。笔者试图总结程序员浪费生命的几种方式,如下。


1、开发一个质量和性能很差的系统

    程序员经常会碰到这样的项目,做出来的系统质量很差,操作无反馈,失败无提示,而且速度很慢,操作时不时要等一会儿。然而,关键是程序员没有机会或者不想参与实施和维护,失去了学习和诊断问题的机会。

2、花费大量人力财力开发一个一次性的项目

这是从事应用开发程序员经常碰到的情况,为某个客户定制化开发一个一次性的项目,然而这个项目要花费巨大的人力成本,最终开发维护周期很长,以巨大亏本收尾或无法收尾。

3、开发一个很漂亮花哨的无人用的系统

    这也是当前常见的情况,客户要做一个亮点政绩工程,要做一个界面漂亮花哨“很炫”的系统,各种图表,各种交互方式、各种监控分析全部堆上,但最终这样的系统是没有人用的。这只是给领导或客人参观用的。

4、全新开发一个原有遗留的系统

     程序员的领导要基于原有的系统重新做一个产品,大幅提升可维护性可扩展性,增加系统的稳定性,减少系统故障。领导决定召集人马,重新进行需求调研,需求分析,架构设计、编码开发测试。但是,这样的事情一再重复,同样类似的需求给不同的客户做了一套又一套新的系统,而且每个系统过一段时间后故障不稳定的情况依旧。各种版本、各种代码库留给了程序员……程序员需要持续给不同客户维护不同版本的系统。

5、开发一个项目范围不确定的系统

    程序员所在的项目,没有人管理项目范围,没有WBS,用户提一点做一点,项目完全没有合同或契约约束,用户要做的越来越多,系统做得越来越大,最终无法控制,客户不满意,程序员也累得半死,试图讨好客户争取更大项目的计划失败。

6、开发一个没有系统角色或涉众的系统

    程序员做的这个项目,虽然都有需求、有功能、有界面,但是奇怪的是,需求没有提到,也没有人知道这些功能是什么人用的。需求没有定义出系统的角色,以及角色所要参与的业务活动。然而这样的项目也不少见,

7、开发一个使用环境不确定的项目

    程序员做的企业应用项目,不知道是给电脑用的还是给移动设备用的,不知道是给IE用的还是其他浏览器用的,不知道是给IE6用的还是IE10用的,不能确定浏览器平台版本。移动设备不知道是iOS还是Android,Android不知道是2.3的还是4.0的,也不能确定手机或平板电脑型号。我们知道,中等规模的企业应用都会比互联网应用要复杂很多,几乎不可能覆盖所有用户的使用终端平台,要做一个优秀系统必须有约束条件,有使用的目标平台。

    针对以上各种情况,程序员经常是没办法干预的,因为,要么这是客户明知故犯的行为,要么是公司部门的战略行为,要么是由于项目经理基本的技能职责缺乏。当然程序员可以假设自己是项目经理,考虑该如何做好这些项目并适时适当的提出问题或解决办法,以免浪费自己的生命。
转载自

IT瘾

随便写点什么。

很久没有更新自己的博客,也许是因为忙,但真的不知道究竟忙了写什么,以后还是有时间就抽点时间来写博客,一方面是长时间不组织语言,有很多想法,说话写字都挤不出半句话来,二来,我需要学会总结,很多经验可能当时很有感触,过一阵就会忘记。不管写的怎么样,坚持写点什么总是好的。看到祥健转载的人民日报一篇文章,有点收获 ,分享一下。

继续阅读“随便写点什么。”

android 屏幕图标尺寸规范

1. 程序启动图标:

ldpi (120 dpi)
小屏

mdpi (160 dpi)
中屏

hdpi (240 dpi)
大屏

xhdpi (320 dpi)
特大屏

36 x 36 px

48 x 48 px

72 x 72 px

96 x 96 px

 

ICON圆角半径

iTunes Artwork icon ───────────────────────── 512px (90px)
App icon(iPhone4) ────────────────────────── 114px (20px)
App icon(iPad) ───────────────────────────── 72px (12px)
App icon(iPhone 3G/3GS) ───────────────────── 57px(10px)
Spotlight/Settings icon icon(iPhone4) ───────────── 58px (10px)
Spotlight/Settings icon icon(iPhone 3G/3GS/iPad) ──── 29px (9px)

 

android中的dialog

在Android开发中,我们经常需要在界面上弹出一些对话框,比如询问用户或者让用户选择。 下面总结了下dialog的一些样式。

 

1.该效果是当按返回按钮时弹出一个提示,来确保无误操作,采用常见的对话框样式。

创建dialog对话框方法代码如下:

  1. protected void dialog() {
  2.     AlertDialog.Builder builder = new Builder(Main.this);
  3.     builder.setMessage(“确认退出吗?”);
  4.     builder.setTitle(“提示”);
  5.     builder.setPositiveButton(“确认”, new OnClickListener() {
  6.      @Override
  7.      public void onClick(DialogInterface dialog, int which) {
  8.       dialog.dismiss();
  9.       Main.this.finish();
  10.      }
  11.     });
  12.     builder.setNegativeButton(“取消”, new OnClickListener() {
  13.      @Override
  14.      public void onClick(DialogInterface dialog, int which) {
  15.       dialog.dismiss();
  16.      }
  17.     });
  18.     builder.create().show();
  19.    }

在onKeyDown(int keyCode, KeyEvent event)方法中调用此方法

  1. public boolean onKeyDown(int keyCode, KeyEvent event) {
  2.     if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
  3.      dialog();
  4.     }
  5.     return false;
  6.    }

2.改变了对话框的图表,添加了三个按钮

创建dialog的方法代码如下:

  1. Dialog dialog = new AlertDialog.Builder(this).setIcon(
  2.        android.R.drawable.btn_star).setTitle(“喜好调查”).setMessage(
  3.        “你喜欢李连杰的电影吗?”).setPositiveButton(“很喜欢”,
  4.        new OnClickListener() {
  5.         @Override
  6.         public void onClick(DialogInterface dialog, int which) {
  7.          // TODO Auto-generated method stub
  8.          Toast.makeText(Main.this, “我很喜欢他的电影。”,
  9.            Toast.LENGTH_LONG).show();
  10.         }
  11.        }).setNegativeButton(“不喜欢”, new OnClickListener() {
  12.       @Override
  13.       public void onClick(DialogInterface dialog, int which) {
  14.        // TODO Auto-generated method stub
  15.        Toast.makeText(Main.this, “我不喜欢他的电影。”, Toast.LENGTH_LONG)
  16.          .show();
  17.       }
  18.      }).setNeutralButton(“一般”, new OnClickListener() {
  19.       @Override
  20.       public void onClick(DialogInterface dialog, int which) {
  21.        // TODO Auto-generated method stub
  22.        Toast.makeText(Main.this, “谈不上喜欢不喜欢。”, Toast.LENGTH_LONG)
  23.          .show();
  24.       }
  25.      }).create();
  26.      dialog.show();

3.信息内容是一个简单的View类型

创建dialog方法的代码如下:

  1. new AlertDialog.Builder(this).setTitle(“请输入”).setIcon(
  2.        android.R.drawable.ic_dialog_info).setView(
  3.        new EditText(this)).setPositiveButton(“确定”, null)
  4.        .setNegativeButton(“取消”, null).show();

4.信息内容是一组单选框

创建dialog方法的代码如下:

  1. new AlertDialog.Builder(this).setTitle(“单选框”).setIcon(
  2.        android.R.drawable.ic_dialog_info).setSingleChoiceItems(
  3.        new String[] { “Item1”, “Item2” }, 0,
  4.        new DialogInterface.OnClickListener() {
  5.         public void onClick(DialogInterface dialog, int which) {
  6.          dialog.dismiss();
  7.         }
  8.        }).setNegativeButton(“取消”, null).show();

 

5.信息内容是一组多选框

创建dialog方法的代码如下:

  1. new AlertDialog.Builder(this).setTitle(“复选框”).setMultiChoiceItems(
  2.        new String[] { “Item1”, “Item2” }, null, null)
  3.        .setPositiveButton(“确定”, null)
  4.        .setNegativeButton(“取消”, null).show();

6.信息内容是一组简单列表项

创建dialog的方法代码如下:

  1. new AlertDialog.Builder(this).setTitle(“列表框”).setItems(
  2.        new String[] { “Item1”, “Item2” }, null).setNegativeButton(
  3.        “确定”, null).show();

7.信息内容是一个自定义的布局

dialog布局文件代码如下:

  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2.   <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
  3.    android:layout_height=”wrap_content” android:layout_width=”wrap_content”
  4.    android:background=”#ffffffff” android:orientation=”horizontal”
  5.    android:id=”@+id/dialog”>
  6.    <TextView android:layout_height=”wrap_content”
  7.      android:layout_width=”wrap_content”
  8.     android:id=”@+id/tvname” android:text=”姓名:” />
  9.    <EditText android:layout_height=”wrap_content”
  10.     android:layout_width=”wrap_content” android:id=”@+id/etname” android:minWidth=”100dip”/>
  11.   </LinearLayout>

创建dialog方法的代码如下:

  1. LayoutInflater inflater = getLayoutInflater();
  2.      View layout = inflater.inflate(R.layout.dialog,
  3.        (ViewGroup) findViewById(R.id.dialog));
  4.      new AlertDialog.Builder(this).setTitle(“自定义布局”).setView(layout)
  5.        .setPositiveButton(“确定”, null)
  6.        .setNegativeButton(“取消”, null).show();

 

好了,以上7种Android dialog对话框的使用方法就介绍到这里了,基本都全了,如果大家在android开发过程中遇到dialog的时候就可以拿出来看看。

android 调用系统设置界面

在编写android应用程序时,如果需要调用系统原生的管理应用程序界面呢?本人在一个项目中遇到过,本人没有发现这方面现成的intent,不过通过看源代码实现了。

android源代码application_settings.xml

  1. <PreferenceScreen  

  2.           android:title="@string/manageapplications_settings_title"  

  3.           android:summary="@string/manageapplications_settings_summary">  

  4.       <intent android:action="android.intent.action.MAIN"  

  5.               android:targetPackage="com.android.settings"  

  6.               android:targetClass="com.android.settings.ManageApplications" />  

  7.   </PreferenceScreen>  


熟悉PreferenceScreen的朋友应该知道如何做了,如果不熟悉的朋友,文章最后贴出一篇文章,大家参考一下就知道了,根据xml的描述,我们可以用如下代码调用系统原生的管理应用程序界面

  1. Intent intent =  new Intent();  

  2. intent.setAction("android.intent.action.MAIN");  

  3. intent.setClassName("com.android.settings", "com.android.settings.ManageApplications");  

  4. startActivity(intent);  

如果要进入某个软件详细设置界面 可以如下操作:  

“Android系统设置->应用程序->管理应用程序”列表下,列出了系统已安装的应用程序。选择其中一个程序,则进入“应用程序信息(Application Info)”界面。这个界面显示了程序名称、版本、存储、权限等信息,并有卸载、停止、清除缓存等按钮,可谓功能不少。如果在编写相关程序时(比如任务管理器)可以调用这个面板,自然提供了很大的方便。那么如何实现呢?

在最新的Android SDK 2.3(API Level 9)中,提供了这样的接口。在文档路径

docs/reference/android/provider/Settings.html#ACTION_APPLICATION_DETAILS_SETTINGS

下,有这样的描述:

public static final String ACTION_APPLICATION_DETAILS_SETTINGS    Since: API Level 9

Activity Action: Show screen of details about a particular application.
In some cases, a matching Activity may not exist, so ensure you safeguard against this.
Input: The Intent's data URI specifies the application package name to be shown, with the "package" scheme. That is "package:com.my.app".
Output: Nothing.
Constant Value: "android.settings.APPLICATION_DETAILS_SETTINGS"

就是说,我们只要以android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS作为Action;package:应用程序的包名作为URI,就可以用startActivity启动应用程序信息界面了。代码如下:

  1. Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);  

  2. Uri uri = Uri.fromParts(SCHEME, packageName, null);  

  3. intent.setData(uri);  

  4. startActivity(intent);  

但是,在Android 2.3之前的版本,并没有公开相关的接口。
通过查看系统设置platform/packages/apps/Settings.git程序的源码,可以发现应用程序信息界面为InstalledAppDetails。
这里(2.1)还有这里(2.2),我们可以分别看到Android2.1Android2.2的应用管理程序(ManageApplications.java)是如何启动InstalledAppDetails的。
  1. // utility method used to start sub activity  

  2. private void startApplicationDetailsActivity() {  

  3.    // Create intent to start new activity  

  4.    Intent intent = new Intent(Intent.ACTION_VIEW);  

  5.    intent.setClass(this, InstalledAppDetails.class);  

  6.    intent.putExtra(APP_PKG_NAME, mCurrentPkgName);  

  7.    // start new activity to display extended information  

  8.    startActivityForResult(intent, INSTALLED_APP_DETAILS);  

  9. }  

但是常量APP_PKG_NAME的定义并不相同。
2.2中定义为"pkg",2.1中定义为"com.android.settings.ApplicationPkgName"
那么,对于2.1及以下版本,我们可以这样调用InstalledAppDetails:
  1. Intent i = new Intent(Intent.ACTION_VIEW);                  

  2. i.setClassName("com.android.settings","com.android.settings.InstalledAppDetails");  

  3. i.putExtra("com.android.settings.ApplicationPkgName", packageName);  

  4. startActivity(i);  

对于2.2,只需替换上面putExtra的第一个参数为"pkg"
综上,通用的调用“应用程序信息”的代码如下:
  1. private static final String SCHEME = "package";  

  2. /**

  3. * 调用系统InstalledAppDetails界面所需的Extra名称(用于Android 2.1及之前版本)

  4. */  

  5. private static final String APP_PKG_NAME_21 = "com.android.settings.ApplicationPkgName";  

  6. /**

  7. * 调用系统InstalledAppDetails界面所需的Extra名称(用于Android 2.2)

  8. */  

  9. private static final String APP_PKG_NAME_22 = "pkg";  

  10. /**

  11. * InstalledAppDetails所在包名

  12. */  

  13. private static final String APP_DETAILS_PACKAGE_NAME = "com.android.settings";  

  14. /**

  15. * InstalledAppDetails类名

  16. */  

  17. private static final String APP_DETAILS_CLASS_NAME = "com.android.settings.InstalledAppDetails";  

  18. /**

  19. * 调用系统InstalledAppDetails界面显示已安装应用程序的详细信息。 对于Android 2.3(Api Level

  20. * 9)以上,使用SDK提供的接口; 2.3以下,使用非公开的接口(查看InstalledAppDetails源码)。

  21. *

  22. * @param context

  23. *

  24. * @param packageName

  25. *            应用程序的包名

  26. */  

  27. public static void showInstalledAppDetails(Context context, String packageName) {  

  28.    Intent intent = new Intent();  

  29.    final int apiLevel = Build.VERSION.SDK_INT;  

  30.    if (apiLevel >= 9) { // 2.3(ApiLevel 9)以上,使用SDK提供的接口  

  31.        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);  

  32.        Uri uri = Uri.fromParts(SCHEME, packageName, null);  

  33.        intent.setData(uri);  

  34.    } else { // 2.3以下,使用非公开的接口(查看InstalledAppDetails源码)  

  35.        // 2.2和2.1中,InstalledAppDetails使用的APP_PKG_NAME不同。  

  36.        final String appPkgName = (apiLevel == 8 ? APP_PKG_NAME_22  

  37.                : APP_PKG_NAME_21);  

  38.        intent.setAction(Intent.ACTION_VIEW);  

  39.        intent.setClassName(APP_DETAILS_PACKAGE_NAME,  

  40.                APP_DETAILS_CLASS_NAME);  

  41.        intent.putExtra(appPkgName, packageName);  

  42.    }  

  43.    context.startActivity(intent);  

  44. }