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

首先给出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. tomcat生命周期的管理——生命周期统一接口Lifecycle

    我们知道Tomcat的架构设计是清晰的.模块化的,其拥有很多组件,假如我们要启动Tomcat,可以一个一个启动组件,但这样启动有很多缺点,不仅麻烦,而且容易漏了组件启动,还会对后面动态组件扩展带来麻烦 ...

  2. Erlang简单并行服务器

    Erlang简单并行服务器(金庆的专栏)Erlang并行服务器为每个Tcp连接创建对应的连接进程,处理客户端数据.参考 Erlang程序设计(第2版)17.1.3 顺序和并行服务器并行服务器的诀窍是: ...

  3. sybase isql命令参数详解

    isql 实用工具使您得以输入 Transact-SQL 语句.系统过程和脚本文件. 语法 isql [-?] | [-L] | [ { {-U login_id [-P password]} | - ...

  4. 基于OpenCV 的美颜相机推送直播流

    程序流程: 1.图像采集 先从opencv(2.4.10版本)采集回来摄像头的图像,是一帧一帧的 每一帧图像是一个矩阵,opencv中的mat 数据结构. 2.人脸的美化 人脸美化,我们用的皮肤检测, ...

  5. 关闭Win10自动更新

    使用过Windows10系统的小伙伴们都清楚,在Windows10中强制开启了自动更新功能,我们无法通过常规的办法关闭自动更新功能,那么我们该怎么去关闭自动更新呢?欢迎速来围观我的经验啦. 工具/原料 ...

  6. Win 10 下 android studio显示 Intel haxm无法安装,以及VT-X和hyper-x的冲突问题

               我 的电脑是神舟战神k650c i7 D4,处理器是Intel core i7 4710-MQ,系统是win 10的 我心血来潮想学习一下安卓开发,就首先安装了android s ...

  7. XMLTABLE

     XMLTABLE Syntax Description of the illustration xmltable.gif XMLnamespaces_clause::= Description ...

  8. Android进阶(十三)网络爬虫&json应用

    刚开始接触网络爬虫,怎一个"菜"字了得!经过几次的折磨,对其原理以及其中用到的json技术有了大致的了解,故作一总结,供有同样迷惑的朋友参考学习. 自己爬取的网站内容为12306的 ...

  9. Android官方命令深入分析之dmtracedump

    dmtracedump是一个根据log文件生成图形化调用堆栈的工具(除了Traceview之外). dmtracedump的用法: dmtracedump [-ho] [-s sortable] [- ...

  10. (七十一)关于UITableView退出崩溃的问题和滚动到底部的方法

    [TableView退出崩溃的问题] 最近在使用TableView时偶然发现在TableView中数据较多时,如果在滚动过程中退出TableView到上一界面,会引起程序的崩溃,经过网上查阅和思考我发 ...