camera开发相关

最近项目用到了相机拍照的功能,于是想着封装好一些通用性较好的相机调用,从百度和谷歌上查找出来的资料真的印证了“天下文章一大抄”的道理,而且它们实 现的拍照功能大都存在缺陷,如聚焦问题、重复拍照问题、照片存储问题、横竖屏转换问题。一大堆的问题,而且程序的扩展性和可重用性实在不敢恭维,排版级其 混乱。

最后无奈,打开API文档camera相机类,从最基础的学起,然后自己进行改进,从这里也告诉我们一个道理,API文档才是学习
起点,因为它会告诉你整个实现的原理和原因,能够对整个框架有一个整体的了解,看完API文档看其他的就有事半功倍的效果,吐槽完毕,下面来正式实现。

一.实现流程

这幅图是从API文档(最好是看英文版的)整理出来的,从这副图上面我们可以看出,主要是有6步,其中难点是创建相机预览类。

二.权限声明

这个不讲了,直接加入声明权限代码,不明白的可以网上查查看

<uses-permission android:name="android.permission.CAMERA" />
	<uses-feature android:name="android.hardware.camera" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
	<uses-feature android:name="android.hardware.camera.autofocus" />
	<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

三 检查相机和获取相机实例

新建CameraCheck类,主要有2个方法,代码如下

public class CameraCheck {

	public static boolean CheckCamera(Context mContext) {
		if (mContext.getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_CAMERA)) {
			return true;
		} else {
			Toast.makeText(mContext, "相机不存在!", Toast.LENGTH_SHORT).show();
			return false;
		}
	}

	/** A safe way to get an instance of the Camera object. */
	public static Camera getCameraInstance(Context mContext) {
		Camera c = null;
		if (CheckCamera(mContext)) {
			try {
				c = Camera.open();
			} catch (Exception e) {
				c=null;
			}
		}
		return c; // returns null if camera is unavailable
	}
}

第一个方法用来检查相机是否存在,这个方法是来自API文档,使用方法

mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)

hasSystemFeature(String name)方法返回设备是否支持name功能的真假值;

通过方法getCameraInstance返回相机的实例,通过调用该方法,mContext能够获得该相机资源,只有获得了该相机资源才能够对相机进行操作。

四.创建相机预览类(重点)

我们在拍照之前需要对取景进行预览,这里我们需要使用SurfaceView控件,关于SurfaceView控件我们先简单的了解一下(别急,磨刀不误砍柴工)。

SurfaceView是View的子类,所以它拥有View的一切方法和属性,这一点我们从命名上面就可以看出来,比如绘制方法、大小等属性;它比
View多了一个Surface的东西,Surface是专门用来绘制的类,而SurfaceView可以控制surface绘制的大小、位置等等;

可能有人会问,那为什么要专门这样一个类来绘制呢?不是有OnDraw()方法吗?相比于OnDraw()方法它有很多优势,如下总结:

(1)在频繁更新UI线程的情况下,可以使用封装好的surface来频繁的更新,因为surface可以使用后台线程对UI界面进行绘制,而OnDraw()等绘制方法很难做到(除非你频繁的调用handler来更新主界面,这得多麻烦啊!);

(2)SurfaceView可以用来绘制2D或者3D图形,绘制一些动态曲线等,它显示的速度会比一般的快很多,因为他是通过硬件加速的方式来绘制的。

(3)它可以用来接受硬件的数据来绘制图像。

所以,通过以上几点我们可以知道,用它来接受相机的预览是理所当然的。那么它的使用方法是怎么样的呢?下创建一个surfaceView的继承类一般需要实现如下几个方法:

(1)surfaceCreated(SurfaceHolderholder):在该类创建的时候调用,这里一般需要实现一些初始化的工作,SurfaceHodler用来设定surface的大小位置等等;

(2)surfaceChanged(SurfaceHolderholder, int format, int width,int height)在surface大小发生改变时候调用,这里实现图形的绘制;

(3)surfaceDestroyed(SurfaceHolderholder)在surface销毁时候调用,这里一般对资源进行释放;

(4)实现SurfaceHodler.CallBack回调方法,在surfaceView创建完成后自动调用类本身;


实现之前我们先来看我们的需求,我们要实现的功能:预览、拍照、自动聚焦、触摸聚焦、连续拍照、照片存储。下面我们来创建一个SurfaceView类
CameraPreview,它继承了SurfaceView,并实现接口SurfaceHolder.Callback

因此我们需要在surfaceCreated方法中创建一个camer实例,这个实例可以在这个类中进行调用,实现代码如下:

/**
	 * 创建的时候自动调用该方法
	 */
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (mCamera == null) {
			mCamera = CameraCheck.getCameraInstance(mContext);
		}
		try {
			if(mCamera!=null){
				mCamera.setPreviewDisplay(holder);
			}
		} catch (IOException e) {
			if (null != mCamera) {
				mCamera.release();
				mCamera = null;
				isPreview=false;
			}
			e.printStackTrace();
		}

	}

这句代码 mCamera.setPreviewDisplay(holder)的意思是创建一个预览的hodler;我们在surfaceChanged中进行预览窗口的绘制调用的是startPreview()方法来开始绘制,代码如下:

/**
	 * 当surface的大小发生改变的时候自动调用的
	 */
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		if (mHolder.getSurface() == null) {
			return;
		}
		try {
			setCameraParms();
			mCamera.setPreviewDisplay(holder);
			mCamera.startPreview();
			reAutoFocus();
		} catch (Exception e) {
			Log.d(TAG, "Error starting camera preview: " + e.getMessage());
		}
	}

其中有2个比较关键的方法没有实现,
setCameraParms()和reAutoFocus(),setCameraParms();函数用来设置预览图片的参数,其中关键的为预览图片
的大小和拍照保存的尺寸大小,很多的网上实现的程序拍出来的照片很小模糊的原因就是没有设置好照片的尺寸,这个照片的尺寸是根据手机本身能够支持的尺寸有
很大关系。reAutoFocus()是自动聚焦的方法,需要动态获取reAutoFocus()函数是自动聚焦的实现;

我们首先来看一下setCameraParms()方法的实现:

private void setCameraParms(){
		Camera.Parameters myParam = mCamera.getParameters();
		List<Camera.Size> mSupportedsizeList =myParam.getSupportedPictureSizes();
		if(mSupportedsizeList.size() > 1) {
			Iterator<Camera.Size> itos = mSupportedsizeList.iterator();
			while (itos.hasNext()){
				Camera.Size curSize = itos.next();
				int curSupporSize=curSize.width * curSize.height;
				int fixPictrueSize= setFixPictureWidth  * setFixPictureHeight;
				if( curSupporSize>fixPictrueSize && curSupporSize <= maxPictureSize) {
					setFixPictureWidth  = curSize.width;
					setFixPictureHeight = curSize.height;
				}
			}
		}<pre name="code" class="java">	if (setFixPictureWidth != 0 && setFixPictureHeight != 0) {
			myParam.setPictureSize(setFixPictureWidth , setFixPictureHeight);
		}

myParam.setJpegQuality(100);mCamera.setParameters(myParam);if
(myParam.getMaxNumDetectedFaces() > 0){
mCamera.startFaceDetection();}}

通过myParam.getSupportedPictureSizes();获取到手机支持的所有尺寸的枚举,并设置最大的固定尺寸这里设置最大为maxPictureSize = 5000000

reAutoFocus()的实现为:

<span style="white-space:pre">	</span>/**
	 * Call the camera to Auto Focus
	 */
	public void reAutoFocus() {
		if (isSupportAutoFocus) {
			mCamera.autoFocus(new AutoFocusCallback() {
				@Override
				public void onAutoFocus(boolean success, Camera camera) {
				}
			});
		}
	}

使用回调函数autoFocus来实现自动聚焦

五.拍照

拍照方法有一个
难点是横竖屏拍照的转换和存储,网上大都实现的是默认的横屏拍照,一旦换成竖屏后预览就会出现问题,而且存储的照片也有问题,因此为了解决这个问题,我们
需要时刻监听方向传感器的变化,得到当前的旋转角度,我么可以通过调用OrientationEventListener系统监听类来得到当前角度,自定
义MyOrientationDetector代码如下:

/**
 * 方向变化监听器,监听传感器方向的改变
 * @author zw.yan
 *
 */
public class MyOrientationDetector extends OrientationEventListener{
	int Orientation;
    public MyOrientationDetector(Context context ) {
        super(context );
    }
    @Override
    public void onOrientationChanged(int orientation) {
        Log.i("MyOrientationDetector ","onOrientationChanged:"+orientation);
        this.Orientation=orientation;
        Log.d("MyOrientationDetector","当前的传感器方向为"+orientation);
    }

    public int getOrientation(){
    	return Orientation;
    }
}

在预览类中我们定义拍照方法TakePhone(),代码如下:

/**
	 * 调整照相的方向,设置拍照相片的方向
	 */
	private void takePhoto() {
		cameraOrientation = new MyOrientationDetector(mContext);
		if (mCamera != null) {
			int orientation = cameraOrientation.getOrientation();
			Camera.Parameters cameraParameter = mCamera.getParameters();
			cameraParameter.setRotation(90);
			cameraParameter.set("rotation", 90);
			if ((orientation >= 45) && (orientation < 135)) {
				cameraParameter.setRotation(180);
				cameraParameter.set("rotation", 180);
			}
			if ((orientation >= 135) && (orientation < 225)) {
				cameraParameter.setRotation(270);
				cameraParameter.set("rotation", 270);
			}
			if ((orientation >= 225) && (orientation < 315)) {
				cameraParameter.setRotation(0);
				cameraParameter.set("rotation", 0);
			}
			mCamera.setParameters(cameraParameter);
			mCamera.takePicture(shutterCallback, pictureCallback, mPicture);
		}
	}

在角度范围内自动调整旋转图片的角度,具体旋转的方式如代码,从而使存储的图片能够正常显示。

六.图片保存

在拍照时需要对图片进行保存,但是不能影响图片的下一次拍照,因此我们需要采用异步线程的方式,可以使用AsyncTask类,在拍照完成时进行调用如下代码:

public class SavePictureTask extends AsyncTask<byte[], String, String> {
		@SuppressLint("SimpleDateFormat")
		@Override
		protected String doInBackground(byte[]... params) {
			File pictureFile = FileUtil.getOutputMediaFile(MEDIA_TYPE_IMAGE,
					mContext);
			if (pictureFile == null) {
				Toast.makeText(mContext, "请插入存储卡!", Toast.LENGTH_SHORT).show();
				return null;
			}
			try {
				FileOutputStream fos = new FileOutputStream(pictureFile);
				fos.write(params[0]);
				fos.flush();
				fos.close();
			} catch (FileNotFoundException e) {
				Log.d(TAG, "File not found: " + e.getMessage());
			} catch (IOException e) {
				Log.d(TAG, "Error accessing file: " + e.getMessage());
			}

			return null;
		}
	}

这是基本对文件异步线程的IO操作有什么不明白的可以去看对应的API文档。

下面我将整个类贴出来:

/** * sufaceView 的预览类,其中SurfaceHolder.CallBack用来监听Surface的变化, * 当Surface发生改变的时候自动调用该回调方法 * 通过调用方SurfaceHolder.addCallBack来绑定该方法 * @author zw.yan * */public class CameraPreview extends SurfaceView implements		SurfaceHolder.Callback {

	private String TAG = "CameraPreview";	/**	 * Surface的控制器,用来控制预览等操作	 */	private SurfaceHolder mHolder;	/**	 * 相机实例	 */	private Camera mCamera = null;	/**	 * 图片处理	 */	public static final int MEDIA_TYPE_IMAGE = 1;	/**	 * 预览状态标志	 */	private boolean isPreview = false;	/**	 * 设置一个固定的最大尺寸	 */	private int maxPictureSize = 5000000;	/**	 * 是否支持自动聚焦,默认不支持	 */	private Boolean isSupportAutoFocus = false;	/**	 * 获取当前的context	 */	private Context mContext;	/**	 * 当前传感器的方向,当方向发生改变的时候能够自动从传感器管理类接受通知的辅助类	 */	MyOrientationDetector cameraOrientation;	/**	 * 设置最适合当前手机的图片宽度	 */	int setFixPictureWidth = 0;	/**	 * 设置当前最适合的图片高度	 */	int setFixPictureHeight = 0;

	@SuppressWarnings("deprecation")	public CameraPreview(Context context) {		super(context);		this.mContext = context;		isSupportAutoFocus = context.getPackageManager().hasSystemFeature(				PackageManager.FEATURE_CAMERA_AUTOFOCUS);		mHolder = getHolder();		//兼容android 3.0以下的API,如果超过3.0则不需要设置该方法		if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB){			mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);		}		mHolder.addCallback(this);//绑定当前的回调方法		}

	/**
	 * 创建的时候自动调用该方法
	 */
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (mCamera == null) {
			mCamera = CameraCheck.getCameraInstance(mContext);
		}
		try {
			if(mCamera!=null){
				mCamera.setPreviewDisplay(holder);
			}
		} catch (IOException e) {
			if (null != mCamera) {
				mCamera.release();
				mCamera = null;
				isPreview=false;
			}
			e.printStackTrace();
		}

	}	/**
	 * 当surface的大小发生改变的时候自动调用的
	 */
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		if (mHolder.getSurface() == null) {
			return;
		}
		try {
			setCameraParms();
			mCamera.setPreviewDisplay(holder);
			mCamera.startPreview();
			reAutoFocus();
		} catch (Exception e) {
			Log.d(TAG, "Error starting camera preview: " + e.getMessage());
		}
	}	private void setCameraParms(){
		Camera.Parameters myParam = mCamera.getParameters();
		List<Camera.Size> mSupportedsizeList =myParam.getSupportedPictureSizes();
		if(mSupportedsizeList.size() > 1) {
			Iterator<Camera.Size> itos = mSupportedsizeList.iterator();
			while (itos.hasNext()){
				Camera.Size curSize = itos.next();
				int curSupporSize=curSize.width * curSize.height;
				int fixPictrueSize= setFixPictureWidth  * setFixPictureHeight;
				if( curSupporSize>fixPictrueSize && curSupporSize <= maxPictureSize) {
					setFixPictureWidth  = curSize.width;
					setFixPictureHeight = curSize.height;
				}
			}
		}<pre name="code" class="java">	if (setFixPictureWidth != 0 && setFixPictureHeight != 0) {
			myParam.setPictureSize(setFixPictureWidth , setFixPictureHeight);
		}<pre name="code" class="java"><span style="white-space:pre">		</span>myParam.setJpegQuality(100);		mCamera.setParameters(myParam);		if (myParam.getMaxNumDetectedFaces() > 0){		       mCamera.startFaceDetection();		}	}

	@Override	public void surfaceDestroyed(SurfaceHolder holder) {		mCamera.stopPreview();		mCamera.release();		mCamera = null;	}

	/**	 * Call the camera to Auto Focus	 */	public void reAutoFocus() {		if (isSupportAutoFocus) {			mCamera.autoFocus(new AutoFocusCallback() {				@Override				public void onAutoFocus(boolean success, Camera camera) {				}			});		}	}	/**	 * 自动聚焦,然后拍照	 */	public void takePicture() {		if (mCamera != null) {			mCamera.autoFocus(autoFocusCallback);		}	}

	private AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {

		public void onAutoFocus(boolean success, Camera camera) {			// TODO Auto-generated method stub

			if (success) {				Log.i(TAG, "autoFocusCallback: success...");				takePhoto();			} else {				Log.i(TAG, "autoFocusCallback: fail...");				if (isSupportAutoFocus) {					takePhoto();				}			}		}	};	/**
	 * 调整照相的方向,设置拍照相片的方向
	 */
	private void takePhoto() {
		cameraOrientation = new MyOrientationDetector(mContext);
		if (mCamera != null) {
			int orientation = cameraOrientation.getOrientation();
			Camera.Parameters cameraParameter = mCamera.getParameters();
			cameraParameter.setRotation(90);
			cameraParameter.set("rotation", 90);
			if ((orientation >= 45) && (orientation < 135)) {
				cameraParameter.setRotation(180);
				cameraParameter.set("rotation", 180);
			}
			if ((orientation >= 135) && (orientation < 225)) {
				cameraParameter.setRotation(270);
				cameraParameter.set("rotation", 270);
			}
			if ((orientation >= 225) && (orientation < 315)) {
				cameraParameter.setRotation(0);
				cameraParameter.set("rotation", 0);
			}
			mCamera.setParameters(cameraParameter);
			mCamera.takePicture(shutterCallback, pictureCallback, mPicture);
		}
	}	private ShutterCallback shutterCallback = new ShutterCallback() {		@Override		public void onShutter() {			// TODO Auto-generated method stub		}	};

	private PictureCallback pictureCallback = new PictureCallback() {

		@Override		public void onPictureTaken(byte[] arg0, Camera arg1) {			// TODO Auto-generated method stub

		}	};	private PictureCallback mPicture = new PictureCallback() {

		@Override		public void onPictureTaken(byte[] data, Camera camera) {			new SavePictureTask().execute(data);			mCamera.startPreview();//重新开始预览		}	};

	public class SavePictureTask extends AsyncTask<byte[], String, String> {
		@SuppressLint("SimpleDateFormat")
		@Override
		protected String doInBackground(byte[]... params) {
			File pictureFile = FileUtil.getOutputMediaFile(MEDIA_TYPE_IMAGE,
					mContext);
			if (pictureFile == null) {
				Toast.makeText(mContext, "请插入存储卡!", Toast.LENGTH_SHORT).show();
				return null;
			}
			try {
				FileOutputStream fos = new FileOutputStream(pictureFile);
				fos.write(params[0]);
				fos.flush();
				fos.close();
			} catch (FileNotFoundException e) {
				Log.d(TAG, "File not found: " + e.getMessage());
			} catch (IOException e) {
				Log.d(TAG, "Error accessing file: " + e.getMessage());
			}

			return null;
		}
	}	@Override	public boolean onTouchEvent(MotionEvent event) {		reAutoFocus();		return false;	}

}

文件的布局和调用如下:

public class CameraActivity extends Activity{

    private CameraPreview mPreview;
	public static final int MEDIA_TYPE_IMAGE = 1;
	public static final int MEDIA_TYPE_VIDEO = 2;
	private String TAG="CameraActivity";
	private FrameLayout preview;
	private ImageButton captureButton;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(R.layout.camera_preview);
        mPreview = new CameraPreview(this);
        preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
        captureButton = (ImageButton) findViewById(R.id.button_capture);
		captureButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				mPreview.takePicture();
			}

		});
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000">
  <FrameLayout
    android:id="@+id/camera_preview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    />

  <ImageButton
    android:id="@+id/button_capture"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@drawable/camera_icon"
    android:background="#00000000"
    />
</LinearLayout>

最终效果如下:

注意,里面有一些类没有具体说明,具体可以查看后面的代码下载链接,有什么不明白的可以发邮件,邮件地址为[email protected]

转载请注明出处,http://blog.csdn.net/itbailei/article/details/38822791代码下载地址:下载地址(别走!请留下你的评论) sorry,刚才看了一下在下载的资源的setCameraParms()方法中忘记设置尺寸大小了,自己下载完后加上,

if (setFixPictureWidth != 0 && setFixPictureHeight != 0) {
			myParam.setPictureSize(setFixPictureWidth , setFixPictureHeight);
		}

对比上面的代码即可!

时间: 2024-10-10 02:09:34

camera开发相关的相关文章

Android Camera开发之基础知识篇

概述 Android框架支持设备的相机拍照和录像功能,你的应用可以直接调用系统的Camera应用来拍照或者录像(比如微信拍照),当然也可以利用Android系统提供的API开发一个Camera应用来实现相机拍照和录像功能(比如市面上流行的360相机).此篇文章主要记录相机开发有关的基础知识,以及带着自己的理解翻译Camera官方文档,如有翻译不恰当支出,还请指出改正.当然我会开一个有关相机开发的一个系列,该系列主要内容包括如下: 相机基本预览拍照功能. 实现相机的Flash,Hdr,滤镜,前后摄

移动端 h5开发相关内容总结——CSS篇

移动端 h5开发相关内容总结——CSS篇 标签: css移动 2016-01-06 15:59 5536人阅读 评论(3) 收藏 举报  分类: HTML+CSS(17)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 1.移动端开发视窗口的添加 h5端开发下面这段话是必须配置的 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=n

WinCE及Windows软件开发相关书籍转让

从开始做WinCE开发到现在已经十多年了,最初可以学习和参考的资料并不多,那时候还没有Stack Overflow,Google也还可以正常访问.遇到问题时,一般都在Google Groups的microsoft.public.windowsce.embedded里提问,有很多热心的朋友,特别是微软的eMVP会帮忙解答或者提供一些思路.另外,也经常看一些博客,微软官方的和一些个人开发者的.这些都让我受益匪浅,也促使我后来在CSDN的WinCE论坛里的活跃并坚持在博客园里写一些博客.盖茨曾在199

IOS游戏开发相关网站

首先记录并分享下我收集到的几个自学时最常用到的一些网站链接. 直接进入正题: 1-Stack Overflow http://stackoverflow.com/ 这个是国外类似于百度知道的网站,但是专注于回答程序开发相关问题,我有非常多的问题都是通过在这里查询解决的,这是我们百度知道所不知道的事情. 2-iOS Developer Library http://developer.apple.com/library/ios/navigation/#section=Resource%20Type

请叫我雷锋———Android应用开发相关下载资源(2014/12/28更新)

Android应用开发相关下载资源 官方终于发布了Android Studio正式版,Android Studio将会成为推荐使用的主要Android开发工具. (1)Android SDK (Android SDK主安装包,包含SDK Manager.AVD Manager.工具包tools,释放后的根文件夹为android-sdk-windows): revision 23.0.2 http://dl.google.com/android/android-sdk_r23.0.2-window

各种与视频编解码以及视频图像处理的应用相关的新技术,新方法,各种软件开发相关的算法,思想。

1. 各种视频压缩标准(MPEG2, MPEG4, H261/2/3/4,X264, T264以及H264(AVC)和HEVC(H265)等的优化,改进,创新. 2. 各种不同平台的(CPU, GPU, DSP, ARM等等)开发,移植优化等, 涉及到的语言包括C, C++, X86汇编,TI DSP汇编,ADI DSP汇编, ARM汇编(armv4/v5/v6/v7 XSCALE WMMX cortex A8等),MMX, SSE, SSE2/3等, 以及目前利用OpenCL来调用GPU实现并

Android TV 开发相关文章

Android TV 开发相关文章 Android TV 开发与Android移动设备开发类似,网络上针对其开发文章较少,平时查阅关于TV 开发资料收集于此,方便日后查阅. 持续更新 --. Android TV 焦点特效实现浅析

我的Android开发相关文章

Pro Android学习笔记: Pro Android学习笔记(一零七):2D动画(2):layout渐变动画 2014.7.25 Pro Android学习笔记(一零六):2D动画(1):frame by frame 2014.7.21 Pro Android学习笔记(一零五):Alarm Manager(3):request code 2014.7.17 Pro Android学习笔记(一零四):Alarm Manager(2):周期发送和取消 2014.7.15 Pro Android学

WINCE 6.0 开发相关问题整理

1. msvc 2005 + wince 5.0 环境搭建:http://hi.baidu.com/hyyly520/item/f9ad7eddffc826362b35c7ef 下载地址:http://blog.csdn.net/weiren2006/article/details/6842807 2. wince 6.0 sdk下载:http://www.blogjava.net/lusm/archive/2007/12/07/166130.html更新下载地址:http://blog.163