项目需要对微信的视频模块也看了一下,在此就对这块进行了一个开发。首先给出效果图

首先给出java代码

/**
 * RecordActivity.java
 * 版权所有(C) 2013
 * 创建:cuiran 2013-10-15 下午3:20:45
 */
package com.app931.oa.activity.video;

import java.io.IOException;
import java.util.List;

import com.app931.oa.R;
import com.app931.oa.util.LogsUtil;
import com.app931.oa.util.SupportedSizesReflect;

import android.app.Activity;
import android.content.Context;

import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Size;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * TODO
 * @author cuiran
 * @version 1.0.0
 */
public class RecordActivity extends Activity implements Callback,MediaPlayer.OnPreparedListener, OnBufferingUpdateListener,
OnCompletionListener
 {
	private static final String TAG="RecordActivity";
	private String videoPath="/sdcard/love.3gp";

	private MediaRecorder mediarecorder;// 录制视频的类
	private MediaPlayer mediaPlayer;//播放视频的类
	private SurfaceView surfaceview;// 显示视频的控件
	private  Camera camera;
	//实现这个接口的Callback接口
	private SurfaceHolder surfaceHolder;
	/**
	 * 是否正在录制true录制中 false未录制
	 */
	private boolean isRecord=false;

	public boolean isCameraBack=true;

	private ImageView recordIv;
	private ImageView recordPlayIv;

	private int mVideoWidth;
	private int mVideoHeight;
	int cameraCount = 0;

	private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.layout_video_record1);
		setTitleStr("");

				// 选择支持半透明模式,在有surfaceview的activity中使用。
		getWindow().setFormat(PixelFormat.TRANSLUCENT);

		initView();

	}

	/**
	 * TODO
	 */
	private void initView() {
		// TODO Auto-generated method stub

		surfaceview = (SurfaceView) this.findViewById(R.id.surfaceview);
		recordIv=(ImageView)findViewById(R.id.recordIv);
		recordPlayIv=(ImageView)findViewById(R.id.recordPlayIv);

		SurfaceHolder holder = surfaceview.getHolder();// 取得holder
		holder.addCallback(this); // holder加入回调接口
		// setType必须设置,要不出错.
		holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

	}
	/**
	 * 播放视频
	 * TODO
	 * @param v
	 */
	public void playVideo(View v){
		recordPlayIv.setVisibility(View.GONE);
		try {
			mediaPlayer=new MediaPlayer();
			mediaPlayer.setDataSource(videoPath);
			mediaPlayer.setDisplay(surfaceHolder);
			mediaPlayer.prepareAsync();

		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		mediaPlayer.setOnBufferingUpdateListener(this);
		mediaPlayer.setOnCompletionListener(this);
		mediaPlayer.setOnPreparedListener(this);
		mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

	}

	/**
	 * 开始录制/停止录制
	 * TODO
	 * @param v
	 */
	public void recordVideo(View v){
		if(isRecord){
			isRecord=false;
			recordIv.setImageResource(R.drawable.video_recorder_start_btn_nor);
			recordPlayIv.setVisibility(View.VISIBLE);
			if (mediarecorder != null) {
				// 停止录制
				mediarecorder.stop();
				// 释放资源
				mediarecorder.release();
				mediarecorder = null;
			}
			if(camera!=null){
				camera.release();
			}
		}else{
			isRecord=true;
			recordIv.setImageResource(R.drawable.video_recorder_recording_btn);
			recordPlayIv.setVisibility(View.GONE);
			mediarecorder = new MediaRecorder();// 创建mediarecorder对象
//			// 从麦克风源进行录音
//			mediarecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
//			// 设置输出格式
//			mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
//			// 设置编码格式
//			mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
			/**
			 * 设置竖着录制
			 */
			if(camera!=null){
				camera.release();
			}

			if(cameraPosition==1){
				camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);//打开摄像头
//				 camera = Camera.open(cameraPosition);//打开摄像头
//		         Camera.Parameters parameters = camera.getParameters();
//		         camera.setDisplayOrientation(90);

//		         camera.setParameters(parameters); 

		         camera=deal(camera);
		         mediarecorder.setOrientationHint(90);//视频旋转90度

			}else{
				camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);//打开摄像头
		         Camera.Parameters parameters = camera.getParameters();
		         camera.setDisplayOrientation(90);
		         camera.setParameters(parameters);
				mediarecorder.setOrientationHint(270);//视频旋转90度
			}

		    camera.unlock();

		    mediarecorder.setCamera(camera);

			// 设置录制视频源为Camera(相机)
			mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
			// 设置录制完成后视频的封装格式THREE_GPP为3gp.MPEG_4为mp4
			mediarecorder
					.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
			// 设置录制的视频编码h263 h264
			mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
			// 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错
			mediarecorder.setVideoSize(176, 144);
			// 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错
			mediarecorder.setVideoFrameRate(20);

			mediarecorder.setPreviewDisplay(surfaceHolder.getSurface());
			// 设置视频文件输出的路径
			mediarecorder.setOutputFile(videoPath);
			try {
				// 准备录制
				mediarecorder.prepare();
				mediarecorder.start();
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}

	protected void setTitleStr(String str) {
			TextView titleText = (TextView) findViewById(R.id.common_title_text);
			titleText.setText(str.trim());

			Button left_button=(Button)findViewById(R.id.left_button);
			left_button.setVisibility(View.VISIBLE);
			left_button.setText("返回");
			left_button.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					back();
				}
			});
			Button right_button=(Button)findViewById(R.id.right_button);
			right_button.setVisibility(View.VISIBLE);
			right_button.setText("");
			right_button.setBackgroundResource(R.drawable.btn_video_switch_bg);
			right_button.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					cameraCount=Camera.getNumberOfCameras();
					if(isCameraBack){
						isCameraBack=false;
					}else{
						isCameraBack=true;
					}
//					SurfaceHolder holder = surfaceview.getHolder();// 取得holder
//					holder.addCallback(RecordActivity.this); // holder加入回调接口
//					LogsUtil.i(TAG, "cameraCount="+cameraCount);

					int cameraCount = 0;
	                CameraInfo cameraInfo = new CameraInfo();
	                cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数

	                for(int i = 0; i < cameraCount; i++) {

	                    Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
	                    if(cameraPosition == 1) {
	                        //现在是后置,变更为前置
	                        if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置  

	                        	camera.stopPreview();//停掉原来摄像头的预览
	                            camera.release();//释放资源
	                            camera = null;//取消原来摄像头
	                            camera = Camera.open(i);//打开当前选中的摄像头
	                            try {
	                            	deal(camera);
	                                camera.setPreviewDisplay(surfaceHolder);//通过surfaceview显示取景画面
	                            } catch (IOException e) {
	                                // TODO Auto-generated catch block
	                                e.printStackTrace();
	                            }
	                            camera.startPreview();//开始预览
	                            cameraPosition = 0;
	                            break;
	                        }
	                    } else {
	                        //现在是前置, 变更为后置
	                        if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置
	                            camera.stopPreview();//停掉原来摄像头的预览
	                            camera.release();//释放资源
	                            camera = null;//取消原来摄像头
	                            camera = Camera.open(i);//打开当前选中的摄像头
	                            try {
	                            	deal(camera);
	                                camera.setPreviewDisplay(surfaceHolder);//通过surfaceview显示取景画面
	                            } catch (IOException e) {
	                                // TODO Auto-generated catch block
	                                e.printStackTrace();
	                            }
	                            camera.startPreview();//开始预览
	                            cameraPosition = 1;
	                            break;
	                        }
	                    }

	                }

				}
			});

	 }

	 /**
	  * 返回
	  *<b>function:</b>
	  *@author cuiran
	  *@createDate 2013-8-20 下午2:22:48
	  */
	 public void back(){

		finish();

	 }

	 public Camera deal(Camera camera){
			//设置camera预览的角度,因为默认图片是倾斜90度的
			camera.setDisplayOrientation(90); 

			Size pictureSize=null;
			Size previewSize=null;
			Camera.Parameters parameters = camera.getParameters();
			parameters.setPreviewFrameRate(5);
			//设置旋转代码
			parameters.setRotation(90);
//			parameters.setPictureFormat(PixelFormat.JPEG);

			List<Size> supportedPictureSizes
			= SupportedSizesReflect.getSupportedPictureSizes(parameters);
			List<Size> supportedPreviewSizes
			= SupportedSizesReflect.getSupportedPreviewSizes(parameters);

			if ( supportedPictureSizes != null &&
					supportedPreviewSizes != null &&
					supportedPictureSizes.size() > 0 &&
					supportedPreviewSizes.size() > 0) {

					//2.x
					pictureSize = supportedPictureSizes.get(0);

					int maxSize = 1280;
					if(maxSize > 0){
						for(Size size : supportedPictureSizes){
							if(maxSize >= Math.max(size.width,size.height)){
								pictureSize = size;
								break;
							}
						}
					}

					WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
					Display display = windowManager.getDefaultDisplay();
					DisplayMetrics displayMetrics = new DisplayMetrics();
					display.getMetrics(displayMetrics);

					previewSize = getOptimalPreviewSize(
										supportedPreviewSizes,
										display.getWidth(),
										display.getHeight()); 

					parameters.setPictureSize(pictureSize.width, pictureSize.height);
					parameters.setPreviewSize(previewSize.width, previewSize.height);								

				}
			camera.setParameters(parameters);
			return camera;
	 }
	/* (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int)
	 */
	@Override
	public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		// 将holder,这个holder为开始在oncreat里面取得的holder,将它赋给surfaceHolder
		surfaceHolder = holder;
	}
	private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }
	/* (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder)
	 */
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		surfaceHolder = holder;

		try {
			if(isCameraBack){
				camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);//打开摄像头

			}else{
				camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);//打开摄像头

			}

			//设置camera预览的角度,因为默认图片是倾斜90度的
			camera.setDisplayOrientation(90); 

			Size pictureSize=null;
			Size previewSize=null;
			Camera.Parameters parameters = camera.getParameters();
			parameters.setPreviewFrameRate(5);
			//设置旋转代码
			parameters.setRotation(90);
//			parameters.setPictureFormat(PixelFormat.JPEG);

			List<Size> supportedPictureSizes
			= SupportedSizesReflect.getSupportedPictureSizes(parameters);
			List<Size> supportedPreviewSizes
			= SupportedSizesReflect.getSupportedPreviewSizes(parameters);

			if ( supportedPictureSizes != null &&
					supportedPreviewSizes != null &&
					supportedPictureSizes.size() > 0 &&
					supportedPreviewSizes.size() > 0) {

					//2.x
					pictureSize = supportedPictureSizes.get(0);

					int maxSize = 1280;
					if(maxSize > 0){
						for(Size size : supportedPictureSizes){
							if(maxSize >= Math.max(size.width,size.height)){
								pictureSize = size;
								break;
							}
						}
					}

					WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
					Display display = windowManager.getDefaultDisplay();
					DisplayMetrics displayMetrics = new DisplayMetrics();
					display.getMetrics(displayMetrics);

					previewSize = getOptimalPreviewSize(
										supportedPreviewSizes,
										display.getWidth(),
										display.getHeight()); 

					parameters.setPictureSize(pictureSize.width, pictureSize.height);
					parameters.setPreviewSize(previewSize.width, previewSize.height);								

				}
			camera.setParameters(parameters);
			camera.setPreviewDisplay(holder);
			camera.startPreview();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/* (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceDestroyed(android.view.SurfaceHolder)
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		if(camera!=null){
			camera.release();
		}
		surfaceview = null;
		surfaceHolder = null;
		if (surfaceHolder != null) {
			surfaceHolder=null;
		}
		if (mediarecorder != null) {
			mediarecorder=null;
		}
		 if (mediaPlayer != null) {
			 mediaPlayer.release();
			 mediaPlayer = null;
		 }

	}

	/* (non-Javadoc)
	 * @see android.media.MediaPlayer.OnCompletionListener#onCompletion(android.media.MediaPlayer)
	 */
	@Override
	public void onCompletion(MediaPlayer arg0) {
		// TODO Auto-generated method stub
		 LogsUtil.i(TAG, "onCompletion");
		 if (mediaPlayer != null) {
			 mediaPlayer.release();
			 mediaPlayer = null;
		 }
		 recordPlayIv.setVisibility(View.VISIBLE);
	}

	/* (non-Javadoc)
	 * @see android.media.MediaPlayer.OnPreparedListener#onPrepared(android.media.MediaPlayer)
	 */
	@Override
	public void onPrepared(MediaPlayer arg0) {
		// TODO Auto-generated method stub
		mVideoWidth = mediaPlayer.getVideoWidth();
		mVideoHeight = mediaPlayer.getVideoHeight();
		  if (mVideoWidth != 0 && mVideoHeight != 0)
		  {

		   /* 设置视频的宽度和高度 */
		   surfaceHolder.setFixedSize(mVideoWidth,mVideoHeight);

		   /* 开始播放 */
		   mediaPlayer.start();
		  }
	}

	/* (non-Javadoc)
	 * @see android.media.MediaPlayer.OnBufferingUpdateListener#onBufferingUpdate(android.media.MediaPlayer, int)
	 */
	@Override
	public void onBufferingUpdate(MediaPlayer player, int arg1) {
		// TODO Auto-generated method stub

	}

}

然后给出布局文件代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:orientation="vertical"
	android:layout_width="fill_parent" android:background="@drawable/login_bj"
	android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">

  <include android:id="@+id/Title"
             android:layout_alignParentTop="true"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             layout="@layout/layout_common_title"/>

  <LinearLayout
       android:layout_below="@+id/Title"
       android:layout_above="@+id/recordBtn"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="30dp"
        >
        <SurfaceView
            android:id="@+id/surfaceview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />

    </LinearLayout>

  <RelativeLayout
    android:id="@+id/videoPlay"
    android:layout_width="fill_parent"
     android:layout_height="fill_parent"
      android:gravity="center"
      >
    <ImageView
      android:src="@drawable/btn_video_play_bg"
      android:id="@+id/recordPlayIv"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:clickable="true"
      android:onClick="playVideo"
      android:visibility="gone"
     />
  </RelativeLayout>

<RelativeLayout
    android:id="@+id/recordBtn"
    android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:gravity="center"
      android:layout_alignParentBottom="true">
     <ImageView
      android:src="@drawable/video_recorder_start_btn_nor"
      android:id="@+id/recordIv"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:clickable="true"
      android:onClick="recordVideo"
     />
</RelativeLayout>

</RelativeLayout>

这里还有一些地方需要完善,在录制完成后切换会出现问题。由于时间关系这边还没去处理,在后续会进行处理,

此代码采用的sdk是17,由于在android 2.2上录制视频是横着,所以采用了高点的sdk

源码demo下载地址:http://pan.baidu.com/s/1jGmk5WM

Android切换前后置摄像头并录制视频的更多相关文章

  1. Android 开发 MediaRecorder使用Camera1配合录制视频

    前言 MediaRecorder可以不依靠Camera API 实现视频的录制,但是如果需要切换摄像头/设置对焦/选择分辨率等等就需要Camera来参与配合录制视频.这篇博客将介绍使用Camera1来 ...

  2. 【Android】 Android实现录音、播音、录制视频功能

    智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...

  3. 【Android Developers Training】 49. 轻松录制视频

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  4. Android自定义view之仿微信录制视频按钮

    本文章只写了个类似微信的录制视频的按钮,效果图如下:             一.主要的功能: 1.长按显示进度条,单击事件,录制完成回调 2.最大时间和最小时间控制 3.进度条宽度,颜色设置 二.实 ...

  5. WebRTC网页打开摄像头并录制视频

    前面我们能打开本地摄像头,并且在网页上看到摄像头的预览图像. 本文我们使用MediaRecorder来录制视频.在网页上播放录制好的视频,并能提供下载功能. html 首先创建一个html界面,放上一 ...

  6. Android开发 MediaRecorder使用Camera2配合录制视频(暂时有异常抛出,无法使用)

    前言 这个博客本来是用来详细介绍MediaRecorder与Camera2,但是出乎预料之外,在获取mMediaRecorder.getSurface();的时候无论如何都是报错的,报错为Surfac ...

  7. Android使用的开发MediaRecorder录制视频

    MediaRecorder除了使用录制音频.还可用于录制视频.关于MediaRecorder的具体解释大家能够參考<Android开发之MediaRecorder类具体解释>.使用Medi ...

  8. android实现前置后置摄像头相互切换

    首先自定义一个继承自SurfaceView并且实现了SurfaceHolder.Callback接口的组件: public class CameraView extends SurfaceView i ...

  9. 使用Android编写录制视频小程序演示样例

    主要实现录制功能的类:Camera类和MediaRecorder类.功能描写叙述:首先进入视频录制界面,点击录像button进入录像功能界面,点击录制開始录制视频, 点击停止button,将录制的视频 ...

随机推荐

  1. [sed]命令笔记

    sed是linux下经常用到的工具,英文全名为stream editor. sed 在windows上的实现可以在这里找到 http://gnuwin32.sourceforge.net/packag ...

  2. Microsoft公司的匈牙利法命名规则

    Microsoft公司的"匈牙利"法命名规则 比较著名的命名规则当推Microsoft公司的"匈牙利"法,该命名规则的主要思想是"在变量和函数名中加入 ...

  3. React Native实现一个自定义模块

    概述 在 前期介绍React Native 项目结构的时候,我们讲解过React的项目组成,其中说过 node_modules 文件夹,这是一个存放 node 模块的地方.我们知道React是用npm ...

  4. 集合框架之Collection接口

    Collection 层次结构中的根接口.Collection表示一组对象,这些对象也称为 collection 的元素.一些 collection 允许有重复的元素,而另一些则不允许.一些 coll ...

  5. Microsoft Dynamics CRM 2011 当您在 大型数据集上执行 RetrieveMultiple 查询很慢的解决方法

    症状 当您在 Microsoft Dynamics CRM 2011 年大型数据集上执行 RetrieveMultiple 查询时,您会比较慢. 原因 发生此问题是因为大型数据集缓存 Retrieve ...

  6. EBS值集,弹性域常用表

      值集 select * from fnd_flex_value_sets select * from fnd_flex_values select * from fnd_flex_valu ...

  7. Python模块探秘 Smtplib发送带有各种附件的邮件

    这两天对Python的邮件模块比较感兴趣,于是就查了查资料.同时在实际的编码过程中也遇到了各种各样的问题.下面我就来分享一下我与smtplib的故事. 前提条件 我的上一篇博文里面讲解了,发送邮件必须 ...

  8. (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 前一篇博文介绍了物理对象中小球与砖块的碰撞处理,在这一篇中我们再 ...

  9. SpriteBuilder实现2D精灵光影明暗反射效果(一)

    其实不用3D建模,用2D的图像就可以模拟3D场景中光照反射的效果. 这里我们不得不提到一个normalMap(法线图)的概念,请各位童鞋自己度娘吧,简单来说它可以使得2D表面生成一定细节程度的光照方向 ...

  10. MTK机器原始OTA更新方法

    在源码中编译完成后会生成各类.img的文件,这时候make otapackage生成ota包 一般ota包在源码工程的out/target/...目录下 一.通过线刷模式 将生成OTA包拷贝到Wind ...