{"id":29297,"date":"2024-11-25T15:35:12","date_gmt":"2024-11-25T07:35:12","guid":{"rendered":"https:\/\/fwq.ai\/blog\/29297\/"},"modified":"2024-11-25T15:35:12","modified_gmt":"2024-11-25T07:35:12","slug":"%e4%bd%bf%e7%94%a8android%e5%ae%9e%e7%8e%b0%e5%be%ae%e4%bf%a1%e5%b0%8f%e8%a7%86%e9%a2%91%e5%bd%95%e5%88%b6%e5%8a%9f%e8%83%bd%e8%af%a6%e7%bb%86%e4%bb%8b%e7%bb%8d","status":"publish","type":"post","link":"https:\/\/fwq.ai\/blog\/29297\/","title":{"rendered":"\u4f7f\u7528Android\u5b9e\u73b0\u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u529f\u80fd\u8be6\u7ec6\u4ecb\u7ecd"},"content":{"rendered":"<p>\u8fd9\u7bc7\u6587\u7ae0\u4e3b\u8981\u4ecb\u7ecd\u4e86android \u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u529f\u80fd\u5b9e\u73b0\u8be6\u89e3\u7684\u76f8\u5173\u8d44\u6599,\u8fd9\u91cc\u63d0\u4f9b\u4e86\u5177\u4f53\u7684\u5b9e\u73b0\u601d\u8def\u53ca\u4ee3\u7801\uff0c\u9700\u8981\u7684\u670b\u53cb\u53ef\u4ee5\u53c2\u8003\u4e0b<\/p>\n<p><strong>Android \u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u529f\u80fd<\/strong><\/p>\n<p>\u5f00\u53d1\u4e4b\u524d<\/p>\n<p>\u8fd9\u51e0\u5929\u63a5\u89e6\u4e86\u4e00\u4e0b\u548c\u89c6\u9891\u76f8\u5173\u7684\u63a7\u4ef6, \u6240\u4ee5, \u7ee7\u4e4b\u524d\u7684\u5fae\u4fe1\u6447\u4e00\u6447, \u6211\u60f3\u5230\u4e86\u6765\u5b9e\u73b0\u4e00\u4e0b\u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u7684\u529f\u80fd, \u5b83\u7684\u529f\u80fd\u70b9\u6bd4\u8f83\u591a, \u6211\u6bcf\u5929\u90fd\u62bd\u51fa\u70b9\u65f6\u95f4\u6765\u5199\u5199, \u8bf4\u5b9e\u8bdd, \u6709\u4e9b\u4e1c\u897f\u8fd8\u662f\u6bd4\u8f83\u8d39\u52b2, \u5e0c\u671b\u5927\u5bb6\u8ba4\u771f\u770b\u770b, \u8bf4\u5f97\u4e0d\u5bf9\u7684\u5730\u65b9\u8fd8\u8bf7\u5927\u5bb6\u5728\u8bc4\u8bba\u4e2d\u6307\u6b63. \u5e9f\u8bdd\u4e0d\u591a\u8bf4, \u8fdb\u5165\u6b63\u9898.<\/p>\n<p>\u5f00\u53d1\u73af\u5883<\/p>\n<p><span>\u70b9\u51fb\u4e0b\u8f7d<\/span>\u201c\u201d\uff1b<\/p>\n<p>\u6700\u8fd1\u521a\u66f4\u65b0\u7684, \u6ca1\u66f4\u65b0\u7684\u5c0f\u4f19\u4f34\u4eec\u6293\u7d27\u4e86<\/p>\n<ol>\n<li>\n<p>Android Studio 2.2.2<\/p>\n<\/li>\n<li>\n<p>JDK1.7<\/p>\n<\/li>\n<li>\n<p>API 24<\/p>\n<\/li>\n<li>\n<p>Gradle 2.2.2<\/p>\n<\/li>\n<\/ol>\n<p>\u76f8\u5173\u77e5\u8bc6\u70b9<\/p>\n<ol>\n<li>\n<p>\u89c6\u9891\u5f55\u5236\u754c\u9762 SurfaceView \u7684\u4f7f\u7528<\/p>\n<\/li>\n<li>\n<p>Camera\u7684\u4f7f\u7528<\/p>\n<\/li>\n<li>\n<p>\u76f8\u673a\u7684\u5bf9\u7126, \u53d8\u7126<\/p>\n<\/li>\n<li>\n<p>\u89c6\u9891\u5f55\u5236\u63a7\u4ef6MediaRecorder\u7684\u4f7f\u7528<\/p>\n<\/li>\n<li>\n<p>\u7b80\u5355\u81ea\u5b9a\u4e49View<\/p>\n<\/li>\n<li>\n<p>GestureDetector(\u624b\u52bf\u68c0\u6d4b)\u7684\u4f7f\u7528<\/p>\n<\/li>\n<\/ol>\n<p>\u7528\u5230\u7684\u4e1c\u897f\u771f\u4e0d\u5c11, \u4e0d\u8fc7\u522b\u7740\u6025, \u54b1\u4eec\u4e00\u4e2a\u4e00\u4e2a\u6765.<\/p>\n<p>\u5f00\u59cb\u5f00\u53d1<\/p>\n<p><strong>\u6848\u4f8b\u5206\u6790<\/strong><\/p>\n<p>\u5927\u5bb6\u53ef\u4ee5\u6253\u5f00\u81ea\u5df1\u5fae\u4fe1\u91cc\u9762\u7684\u5c0f\u89c6\u9891, \u4e00\u5757\u7b80\u5355\u7684\u5206\u6790\u4e00\u4e0b\u5b83\u7684\u529f\u80fd\u70b9\u6709\u54ea\u4e9b ?<\/p>\n<ol>\n<li>\n<p>\u57fa\u672c\u7684\u89c6\u9891\u9884\u89c8\u529f\u80fd<\/p>\n<\/li>\n<li>\n<p>\u957f\u6309 \u201c\u6309\u4f4f\u62cd\u201d \u5b9e\u73b0\u89c6\u9891\u7684\u5f55\u5236<\/p>\n<\/li>\n<li>\n<p>\u5f55\u5236\u8fc7\u7a0b\u4e2d\u7684\u8fdb\u5ea6\u6761\u4ece\u4e24\u4fa7\u5411\u4e2d\u95f4\u53d8\u77ed<\/p>\n<\/li>\n<li>\n<p>\u5f53\u677e\u624b\u6216\u8005\u8fdb\u5ea6\u6761\u8d70\u5230\u5c3d\u5934\u89c6\u9891\u505c\u6b62\u5f55\u5236 \u5e76\u4fdd\u5b58<\/p>\n<\/li>\n<li>\n<p>\u4ece \u201c\u6309\u4f4f\u62cd\u201d \u4e0a\u6ed1\u53d6\u6d88\u89c6\u9891\u7684\u5f55\u5236<\/p>\n<\/li>\n<li>\n<p>\u53cc\u51fb\u5c4f\u5e55 \u53d8\u7126 \u653e\u5927<\/p>\n<\/li>\n<\/ol>\n<p>\u6839\u636e\u4e0a\u8ff0\u7684\u5206\u6790, \u6211\u4eec\u4e00\u6b65\u4e00\u6b65\u7684\u5b8c\u6210<\/p>\n<p><strong>\u642d\u5efa\u5e03\u5c40<\/strong><\/p>\n<p>\u5e03\u5c40\u754c\u9762\u7684\u5b9e\u73b0\u8fd8\u53ef\u4ee5, \u96be\u5ea6\u4e0d\u5927<\/p>\n<p><\/p>\n<pre>&lt;?xml  version=\"1.0\" encoding=\"utf-8\"?&gt;&lt;framelayout&gt;\r\n&nbsp;&nbsp;&lt;textview&gt;&lt;\/textview&gt;\r\n&nbsp;&nbsp;&lt;linearlayout&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;surfaceview&gt;&lt;\/surfaceview&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;linearlayout&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;relativelayout&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;com.lulu.weichatsamplevideo.bothwayprogressbar&gt;&lt;\/com.lulu.weichatsamplevideo.bothwayprogressbar&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;textview&gt;&lt;\/textview&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;\/relativelayout&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;\/linearlayout&gt;\r\n&nbsp;&nbsp;&lt;\/linearlayout&gt;&lt;\/framelayout&gt;<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p><strong>\u89c6\u9891\u9884\u89c8\u7684\u5b9e\u73b0<\/strong><\/p>\n<p>step1: \u5f97\u5230SufaceView\u63a7\u4ef6, \u8bbe\u7f6e\u57fa\u672c\u5c5e\u6027\u548c\u76f8\u5e94\u76d1\u542c(\u8be5\u63a7\u4ef6\u7684\u521b\u5efa\u662f\u5f02\u6b65\u7684, \u53ea\u6709\u5728\u771f\u6b63\u201d\u51c6\u5907\u201d\u597d\u4e4b\u540e\u624d\u80fd\u8c03\u7528)<\/p>\n<p><\/p>\n<pre>mSurfaceView&nbsp;=&nbsp;(SurfaceView)&nbsp;findViewById(R.id.main_surface_view);\r\n&nbsp;\/\/\u8bbe\u7f6e\u5c4f\u5e55\u5206\u8fa8\u7387\r\nmSurfaceHolder.setFixedSize(videoWidth,&nbsp;videoHeight);\r\nmSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);\r\nmSurfaceHolder.addCallback(this);<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>step2: \u5b9e\u73b0\u63a5\u53e3\u7684\u65b9\u6cd5, surfaceCreated\u65b9\u6cd5\u4e2d\u5f00\u542f\u89c6\u9891\u7684\u9884\u89c8, \u5728surfaceDestroyed\u4e2d\u9500\u6bc1<\/p>\n<p><\/p>\n<pre>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/&nbsp;SurfaceView\u56de\u8c03\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n@Override\r\npublic&nbsp;void&nbsp;surfaceCreated(SurfaceHolder&nbsp;holder)&nbsp;{\r\n&nbsp;&nbsp;mSurfaceHolder&nbsp;=&nbsp;holder;\r\n&nbsp;&nbsp;startPreView(holder);\r\n}\r\n@Override\r\npublic&nbsp;void&nbsp;surfaceChanged(SurfaceHolder&nbsp;holder,&nbsp;int&nbsp;format,&nbsp;int&nbsp;width,&nbsp;int&nbsp;height)&nbsp;{\r\n\r\n}\r\n\r\n@Override\r\npublic&nbsp;void&nbsp;surfaceDestroyed(SurfaceHolder&nbsp;holder)&nbsp;{\r\n&nbsp;&nbsp;if&nbsp;(mCamera&nbsp;!=&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;Log.d(TAG,&nbsp;\"surfaceDestroyed:&nbsp;\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u505c\u6b62\u9884\u89c8\u5e76\u91ca\u653e\u6444\u50cf\u5934\u8d44\u6e90\r\n&nbsp;&nbsp;&nbsp;&nbsp;mCamera.stopPreview();\r\n&nbsp;&nbsp;&nbsp;&nbsp;mCamera.release();\r\n&nbsp;&nbsp;&nbsp;&nbsp;mCamera&nbsp;=&nbsp;null;\r\n&nbsp;&nbsp;}\r\n&nbsp;&nbsp;if&nbsp;(mMediaRecorder&nbsp;!=&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.release();\r\n&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder&nbsp;=&nbsp;null;\r\n&nbsp;&nbsp;}\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>step3: \u5b9e\u73b0\u89c6\u9891\u9884\u89c8\u7684\u65b9\u6cd5<\/p>\n<p><\/p>\n<pre>\/**\r\n&nbsp;*&nbsp;\u5f00\u542f\u9884\u89c8\r\n&nbsp;*\r\n&nbsp;*&nbsp;@param&nbsp;holder\r\n&nbsp;*\/\r\nprivate&nbsp;void&nbsp;startPreView(SurfaceHolder&nbsp;holder)&nbsp;{\r\n&nbsp;&nbsp;Log.d(TAG,&nbsp;\"startPreView:&nbsp;\");\r\n\r\n&nbsp;&nbsp;if&nbsp;(mCamera&nbsp;==&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;mCamera&nbsp;=&nbsp;Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);\r\n&nbsp;&nbsp;}\r\n&nbsp;&nbsp;if&nbsp;(mMediaRecorder&nbsp;==&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder&nbsp;=&nbsp;new&nbsp;MediaRecorder();\r\n&nbsp;&nbsp;}\r\n&nbsp;&nbsp;if&nbsp;(mCamera&nbsp;!=&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;mCamera.setDisplayOrientation(90);\r\n&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mCamera.setPreviewDisplay(holder);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Camera.Parameters&nbsp;parameters&nbsp;=&nbsp;mCamera.getParameters();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u5b9e\u73b0Camera\u81ea\u52a8\u5bf9\u7126\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;string&gt;&nbsp;focusModes&nbsp;=&nbsp;parameters.getSupportedFocusModes();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(focusModes&nbsp;!=&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(String&nbsp;mode&nbsp;:&nbsp;focusModes)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mode.contains(\"continuous-video\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters.setFocusMode(\"continuous-video\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mCamera.setParameters(parameters);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mCamera.startPreview();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(IOException&nbsp;e)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n}&lt;\/string&gt;<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>Note: \u4e0a\u9762\u6dfb\u52a0\u4e86\u81ea\u52a8\u5bf9\u7126\u7684\u4ee3\u7801, \u4f46\u662f\u90e8\u5206\u624b\u673a\u53ef\u80fd\u4e0d\u652f\u6301<\/p>\n<p><strong>\u81ea\u5b9a\u4e49\u53cc\u5411\u7f29\u51cf\u7684\u8fdb\u5ea6\u6761<\/strong><\/p>\n<p>\u6709\u4e9b\u50cf\u6211\u4e00\u6837\u7684\u521d\u5b66\u8005\u4e00\u770b\u5230\u81ea\u5b9a\u4e49\u67d0\u67d0View, \u5c31\u89c9\u5f97\u6bd4\u8f83\u725bX. \u5176\u5b9e\u5462, Google\u5df2\u7ecf\u66ff\u6211\u4eec\u5199\u597d\u4e86\u5f88\u591a\u4ee3\u7801, \u6240\u4ee5\u6211\u4eec\u7528\u5c31\u884c\u4e86.\u800c\u4e14\u54b1\u4eec\u7684\u8fd9\u4e2a\u8fdb\u5ea6\u6761\u4e5f\u6ca1\u5565, \u4e0d\u5c31\u662f\u4e00\u6839\u7ebf, \u4eca\u5929\u54b1\u5c31\u6765\u8bf4\u8bf4.<\/p>\n<p>step1: \u7ee7\u627fView, \u5b8c\u6210\u521d\u59cb\u5316<\/p>\n<p><\/p>\n<pre>private&nbsp;static&nbsp;final&nbsp;String&nbsp;TAG&nbsp;=&nbsp;\"BothWayProgressBar\";\r\n\/\/\u53d6\u6d88\u72b6\u6001\u4e3a\u7ea2\u8272bar,&nbsp;\u53cd\u4e4b\u4e3a\u7eff\u8272bar\r\nprivate&nbsp;boolean&nbsp;isCancel&nbsp;=&nbsp;false;\r\nprivate&nbsp;Context&nbsp;mContext;\r\n\/\/\u6b63\u5728\u5f55\u5236\u7684\u753b\u7b14\r\nprivate&nbsp;Paint&nbsp;mRecordPaint;\r\n\/\/\u4e0a\u6ed1\u53d6\u6d88\u65f6\u7684\u753b\u7b14\r\nprivate&nbsp;Paint&nbsp;mCancelPaint;\r\n\/\/\u662f\u5426\u663e\u793a\r\nprivate&nbsp;int&nbsp;mVisibility;\r\n\/\/&nbsp;\u5f53\u524d\u8fdb\u5ea6\r\nprivate&nbsp;int&nbsp;progress;\r\n\/\/\u8fdb\u5ea6\u6761\u7ed3\u675f\u7684\u76d1\u542c\r\nprivate&nbsp;OnProgressEndListener&nbsp;mOnProgressEndListener;\r\n\r\npublic&nbsp;BothWayProgressBar(Context&nbsp;context)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;super(context,&nbsp;null);\r\n}\r\npublic&nbsp;BothWayProgressBar(Context&nbsp;context,&nbsp;AttributeSet&nbsp;attrs)&nbsp;{\r\n&nbsp;&nbsp;super(context,&nbsp;attrs);\r\n&nbsp;&nbsp;mContext&nbsp;=&nbsp;context;\r\n&nbsp;&nbsp;init();\r\n}\r\nprivate&nbsp;void&nbsp;init()&nbsp;{\r\n&nbsp;&nbsp;mVisibility&nbsp;=&nbsp;INVISIBLE;\r\n&nbsp;&nbsp;mRecordPaint&nbsp;=&nbsp;new&nbsp;Paint();\r\n&nbsp;&nbsp;mRecordPaint.setColor(Color.GREEN);\r\n&nbsp;&nbsp;mCancelPaint&nbsp;=&nbsp;new&nbsp;Paint();\r\n&nbsp;&nbsp;mCancelPaint.setColor(Color.RED);\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>Note: OnProgressEndListener, \u4e3b\u8981\u7528\u4e8e\u5f53\u8fdb\u5ea6\u6761\u8d70\u5230\u4e2d\u95f4\u4e86, \u597d\u901a\u77e5\u76f8\u673a\u505c\u6b62\u5f55\u5236, \u63a5\u53e3\u5982\u4e0b:<\/p>\n<p><\/p>\n<pre>public&nbsp;interface&nbsp;OnProgressEndListener{\r\n&nbsp;&nbsp;void&nbsp;onProgressEndListener();\r\n}\r\n\/**\r\n&nbsp;*&nbsp;\u5f53\u8fdb\u5ea6\u6761\u7ed3\u675f\u540e\u7684&nbsp;\u76d1\u542c\r\n&nbsp;*&nbsp;@param&nbsp;onProgressEndListener\r\n&nbsp;*\/\r\npublic&nbsp;void&nbsp;setOnProgressEndListener(OnProgressEndListener&nbsp;onProgressEndListener)&nbsp;{\r\n&nbsp;&nbsp;mOnProgressEndListener&nbsp;=&nbsp;onProgressEndListener;\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>step2 :\u8bbe\u7f6eSetter\u65b9\u6cd5\u7528\u4e8e\u901a\u77e5\u6211\u4eec\u7684Progress\u6539\u53d8\u72b6\u6001<\/p>\n<p><\/p>\n<pre>\/**\r\n&nbsp;*&nbsp;\u8bbe\u7f6e\u8fdb\u5ea6\r\n&nbsp;*&nbsp;@param&nbsp;progress\r\n&nbsp;*\/\r\npublic&nbsp;void&nbsp;setProgress(int&nbsp;progress)&nbsp;{\r\n&nbsp;&nbsp;this.progress&nbsp;=&nbsp;progress;\r\n&nbsp;&nbsp;invalidate();\r\n}\r\n\r\n\/**\r\n&nbsp;*&nbsp;\u8bbe\u7f6e\u5f55\u5236\u72b6\u6001&nbsp;\u662f\u5426\u4e3a\u53d6\u6d88\u72b6\u6001\r\n&nbsp;*&nbsp;@param&nbsp;isCancel\r\n&nbsp;*\/\r\npublic&nbsp;void&nbsp;setCancel(boolean&nbsp;isCancel)&nbsp;{\r\n&nbsp;&nbsp;this.isCancel&nbsp;=&nbsp;isCancel;\r\n&nbsp;&nbsp;invalidate();\r\n}\r\n\/**\r\n&nbsp;*&nbsp;\u91cd\u5199\u662f\u5426\u53ef\u89c1\u65b9\u6cd5\r\n&nbsp;*&nbsp;@param&nbsp;visibility\r\n&nbsp;*\/\r\n@Override\r\npublic&nbsp;void&nbsp;setVisibility(int&nbsp;visibility)&nbsp;{\r\n&nbsp;&nbsp;mVisibility&nbsp;=&nbsp;visibility;\r\n&nbsp;&nbsp;\/\/\u91cd\u65b0\u7ed8\u5236\r\n&nbsp;&nbsp;invalidate();\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>step3 :\u6700\u91cd\u8981\u7684\u4e00\u6b65, \u753b\u51fa\u6211\u4eec\u7684\u8fdb\u5ea6\u6761,\u4f7f\u7528\u7684\u5c31\u662fView\u4e2d\u7684onDraw(Canvas canvas)\u65b9\u6cd5<\/p>\n<p><\/p>\n<pre>@Override\r\nprotected&nbsp;void&nbsp;onDraw(Canvas&nbsp;canvas)&nbsp;{\r\n&nbsp;&nbsp;super.onDraw(canvas);\r\n&nbsp;&nbsp;if&nbsp;(mVisibility&nbsp;==&nbsp;View.VISIBLE)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;height&nbsp;=&nbsp;getHeight();\r\n&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;width&nbsp;=&nbsp;getWidth();\r\n&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;mid&nbsp;=&nbsp;width&nbsp;\/&nbsp;2;\r\n\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u753b\u51fa\u8fdb\u5ea6\u6761\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(progress&nbsp;&lt;p&gt;\u5f55\u5236\u4e8b\u4ef6\u7684\u5904\u7406&lt;\/p&gt;&lt;p&gt;\u5f55\u5236\u4e2d\u89e6\u53d1\u7684\u4e8b\u4ef6\u5305\u62ec\u56db\u4e2a:&lt;\/p&gt;&lt;ol class=\" list-paddingleft-2\"&gt;\n&lt;li&gt;&lt;p&gt;\u957f\u6309\u5f55\u5236&lt;\/p&gt;&lt;\/li&gt;\n&lt;li&gt;&lt;p&gt;\u62ac\u8d77\u4fdd\u5b58&lt;\/p&gt;&lt;\/li&gt;\n&lt;li&gt;&lt;p&gt;\u4e0a\u6ed1\u53d6\u6d88&lt;\/p&gt;&lt;\/li&gt;\n&lt;li&gt;&lt;p&gt;\u53cc\u51fb\u653e\u5927(\u53d8\u7126)&nbsp;&lt;\/p&gt;&lt;\/li&gt;\n&lt;\/ol&gt;&lt;p&gt;&nbsp;\u73b0\u5728\u5bf9\u8fd94\u4e2a\u4e8b\u4ef6\u9010\u4e2a\u5206\u6790: &lt;br&gt;\u524d\u4e09\u8fd9\u4e2a\u4e8b\u4ef6, \u6211\u90fd\u653e\u5728\u4e86\u4e00\u4e2aonTouch()\u56de\u8c03\u65b9\u6cd5\u4e2d\u4e86 &lt;br&gt;\u5bf9\u4e8e\u7b2c4\u4e2a, \u6211\u4eec\u5f85\u4f1a\u8c08 &lt;br&gt;\u6211\u4eec\u5148\u628aonTouch()\u4e2d\u5c40\u90e8\u53d8\u91cf\u5217\u4e3e\u4e00\u4e0b:&lt;\/p&gt;&lt;p class=\"jb51code\"&gt;&lt;br&gt;&lt;\/p&gt;&lt;pre class=\"brush:java;\"&gt;@Override\r\npublic&nbsp;boolean&nbsp;onTouch(View&nbsp;v,&nbsp;MotionEvent&nbsp;event)&nbsp;{\r\n&nbsp;&nbsp;boolean&nbsp;ret&nbsp;=&nbsp;false;\r\n&nbsp;&nbsp;int&nbsp;action&nbsp;=&nbsp;event.getAction();\r\n&nbsp;&nbsp;float&nbsp;ey&nbsp;=&nbsp;event.getY();\r\n&nbsp;&nbsp;float&nbsp;ex&nbsp;=&nbsp;event.getX();\r\n&nbsp;&nbsp;\/\/\u53ea\u76d1\u542c\u4e2d\u95f4\u7684\u6309\u94ae\u5904\r\n&nbsp;&nbsp;int&nbsp;vW&nbsp;=&nbsp;v.getWidth();\r\n&nbsp;&nbsp;int&nbsp;left&nbsp;=&nbsp;LISTENER_START;\r\n&nbsp;&nbsp;int&nbsp;right&nbsp;=&nbsp;vW&nbsp;-&nbsp;LISTENER_START;\r\n&nbsp;&nbsp;float&nbsp;downY&nbsp;=&nbsp;0;\r\n&nbsp;&nbsp;\/\/&nbsp;...\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p><strong>\u957f\u6309\u5f55\u5236<\/strong><\/p>\n<p>\u957f\u6309\u5f55\u5236\u6211\u4eec\u9700\u8981\u76d1\u542cACTION_DOWN\u4e8b\u4ef6, \u4f7f\u7528\u7ebf\u7a0b\u5ef6\u8fdf\u53d1\u9001Handler\u6765\u5b9e\u73b0\u8fdb\u5ea6\u6761\u7684\u66f4\u65b0<\/p>\n<p><\/p>\n<pre>switch&nbsp;(action)&nbsp;{\r\n&nbsp;case&nbsp;MotionEvent.ACTION_DOWN:\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(ex&nbsp;&amp;gt;&nbsp;left&nbsp;&amp;amp;&amp;amp;&nbsp;ex&nbsp;&lt;p&gt;Note: startRecord()\u8fd9\u4e2a\u65b9\u6cd5\u5148\u4e0d\u8bf4, \u6211\u4eec\u53ea\u9700\u8981\u77e5\u9053\u6267\u884c\u4e86\u5b83\u5c31\u53ef\u4ee5\u5f55\u5236\u4e86, \u4f46\u662fHandler\u4e8b\u4ef6\u8fd8\u662f\u8981\u8bf4\u7684, \u5b83\u53ea\u8d1f\u8d23\u66f4\u65b0\u8fdb\u5ea6\u6761\u7684\u8fdb\u5ea6&lt;\/p&gt;&lt;p class=\"jb51code\"&gt;&lt;br&gt;&lt;\/p&gt;&lt;pre class=\"brush:java;\"&gt;\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/&nbsp;Handler\u5904\u7406\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\nprivate&nbsp;static&nbsp;class&nbsp;MyHandler&nbsp;extends&nbsp;Handler&nbsp;{\r\n&nbsp;&nbsp;private&nbsp;WeakReference&lt;mainactivity&gt;&nbsp;mReference;\r\n&nbsp;&nbsp;private&nbsp;MainActivity&nbsp;mActivity;\r\n\r\n&nbsp;&nbsp;public&nbsp;MyHandler(MainActivity&nbsp;activity)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;mReference&nbsp;=&nbsp;new&nbsp;WeakReference&lt;mainactivity&gt;(activity);\r\n&nbsp;&nbsp;&nbsp;&nbsp;mActivity&nbsp;=&nbsp;mReference.get();\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;@Override\r\n&nbsp;&nbsp;public&nbsp;void&nbsp;handleMessage(Message&nbsp;msg)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(msg.what)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;0:\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mActivity.mProgressBar.setProgress(mActivity.mProgress);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n}&lt;\/mainactivity&gt;&lt;\/mainactivity&gt;<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p><strong>\u62ac\u8d77\u4fdd\u5b58<\/strong><\/p>\n<p>\u540c\u6837\u6211\u4eec\u8fd9\u513f\u9700\u8981\u76d1\u542cACTION_UP\u4e8b\u4ef6, \u4f46\u662f\u8981\u8003\u8651\u5f53\u7528\u6237\u62ac\u8d77\u8fc7\u5feb\u65f6(\u5f55\u5236\u7684\u65f6\u95f4\u8fc7\u77ed), \u4e0d\u9700\u8981\u4fdd\u5b58. \u800c\u4e14, \u5728\u8fd9\u4e2a\u4e8b\u4ef6\u4e2d\u5305\u542b\u4e86\u53d6\u6d88\u72b6\u6001\u7684\u62ac\u8d77, \u89e3\u91ca\u4e00\u4e0b: \u5c31\u662f\u5f53\u4e0a\u6ed1\u53d6\u6d88\u65f6\u62ac\u8d77\u7684\u4e00\u77ac\u95f4\u53d6\u6d88\u5f55\u5236, \u5927\u5bb6\u770b\u4ee3\u7801<\/p>\n<p><\/p>\n<pre>case&nbsp;MotionEvent.ACTION_UP:\r\n&nbsp;if&nbsp;(ex&nbsp;&amp;gt;&nbsp;left&nbsp;&amp;amp;&amp;amp;&nbsp;ex&nbsp;&lt;p&gt;Note: \u540c\u6837\u7684, \u5185\u90e8\u7684stopRecordUnSave()\u548cstopRecordSave();\u5927\u5bb6\u5148\u4e0d\u8981\u8003\u8651, \u6211\u4eec\u4f1a\u5728\u540e\u9762\u4ecb\u7ecd, \u4ed6\u4fe9\u4ece\u540d\u5b57\u5c31\u80fd\u770b\u51fa \u524d\u8005\u7528\u6765\u505c\u6b62\u5f55\u5236\u4f46\u4e0d\u4fdd\u5b58, \u540e\u8005\u505c\u6b62\u5f55\u5236\u5e76\u4fdd\u5b58&lt;br&gt;&lt;\/p&gt;&lt;p&gt;&lt;strong&gt;\u4e0a\u6ed1\u53d6\u6d88&lt;\/strong&gt;&lt;\/p&gt;&lt;p&gt;\u914d\u5408\u4e0a\u4e00\u90e8\u5206\u8bf4\u5f97\u62ac\u8d77\u53d6\u6d88\u4e8b\u4ef6, \u5b9e\u73b0\u4e0a\u6ed1\u53d6\u6d88&lt;\/p&gt;&lt;p class=\"jb51code\"&gt;&lt;br&gt;&lt;\/p&gt;&lt;pre class=\"brush:java;\"&gt;case&nbsp;MotionEvent.ACTION_MOVE:\r\n&nbsp;if&nbsp;(ex&nbsp;&amp;gt;&nbsp;left&nbsp;&amp;amp;&amp;amp;&nbsp;ex&nbsp;&nbsp;10)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isCancel&nbsp;=&nbsp;true;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mProgressBar.setCancel(true);\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;}\r\n&nbsp;break;<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>Note: \u4e3b\u8981\u539f\u7406\u4e0d\u96be, \u53ea\u8981\u6309\u4e0b\u5e76\u4e14\u5411\u4e0a\u79fb\u52a8\u4e00\u5b9a\u8ddd\u79bb \u5c31\u4f1a\u89e6\u53d1,\u5f53\u624b\u62ac\u8d77\u65f6\u89c6\u9891\u5f55\u5236\u53d6\u6d88<\/p>\n<p><strong>\u53cc\u51fb\u653e\u5927(\u53d8\u7126)<\/strong><\/p>\n<p>\u8fd9\u4e2a\u4e8b\u4ef6\u6bd4\u8f83\u7279\u6b8a, \u4f7f\u7528\u4e86Google\u63d0\u4f9b\u7684GestureDetector\u624b\u52bf\u68c0\u6d4b \u6765\u5224\u65ad\u53cc\u51fb\u4e8b\u4ef6<\/p>\n<p>step1: \u5bf9SurfaceView\u8fdb\u884c\u5355\u72ec\u7684Touch\u4e8b\u4ef6\u76d1\u542c, why? \u56e0\u4e3aGestureDetector\u9700\u8981Touch\u4e8b\u4ef6\u7684\u5b8c\u5168\u6258\u7ba1, \u5982\u679c\u53ea\u7ed9\u5b83\u4f20\u90e8\u5206\u4e8b\u4ef6\u4f1a\u9020\u6210\u67d0\u4e9b\u4e8b\u4ef6\u5931\u6548<\/p>\n<p><\/p>\n<pre>mDetector&nbsp;=&nbsp;new&nbsp;GestureDetector(this,&nbsp;new&nbsp;ZoomGestureListener());\r\n\/**\r\n&nbsp;*&nbsp;\u5355\u72ec\u5904\u7406mSurfaceView\u7684\u53cc\u51fb\u4e8b\u4ef6\r\n&nbsp;*\/\r\nmSurfaceView.setOnTouchListener(new&nbsp;View.OnTouchListener()&nbsp;{\r\n&nbsp;&nbsp;@Override\r\n&nbsp;&nbsp;public&nbsp;boolean&nbsp;onTouch(View&nbsp;v,&nbsp;MotionEvent&nbsp;event)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;mDetector.onTouchEvent(event);\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;\r\n&nbsp;&nbsp;}\r\n});<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>step2: \u91cd\u5199GestureDetector.SimpleOnGestureListener, \u5b9e\u73b0\u53cc\u51fb\u4e8b\u4ef6<\/p>\n<p><\/p>\n<pre>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/&nbsp;\u53d8\u7126\u624b\u52bf\u5904\u7406\u7c7b\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\nclass&nbsp;ZoomGestureListener&nbsp;extends&nbsp;GestureDetector.SimpleOnGestureListener&nbsp;{\r\n&nbsp;&nbsp;\/\/\u53cc\u51fb\u624b\u52bf\u4e8b\u4ef6\r\n&nbsp;&nbsp;@Override\r\n&nbsp;&nbsp;public&nbsp;boolean&nbsp;onDoubleTap(MotionEvent&nbsp;e)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;super.onDoubleTap(e);\r\n&nbsp;&nbsp;&nbsp;&nbsp;Log.d(TAG,&nbsp;\"onDoubleTap:&nbsp;\u53cc\u51fb\u4e8b\u4ef6\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(mMediaRecorder&nbsp;!=&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!isZoomIn)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setZoom(20);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isZoomIn&nbsp;=&nbsp;true;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setZoom(0);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isZoomIn&nbsp;=&nbsp;false;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;\r\n&nbsp;&nbsp;}\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>step3: \u5b9e\u73b0\u76f8\u673a\u7684\u53d8\u7126\u7684\u65b9\u6cd5<\/p>\n<p><\/p>\n<pre>\/**\r\n&nbsp;*&nbsp;\u76f8\u673a\u53d8\u7126\r\n&nbsp;*\r\n&nbsp;*&nbsp;@param&nbsp;zoomValue\r\n&nbsp;*\/\r\npublic&nbsp;void&nbsp;setZoom(int&nbsp;zoomValue)&nbsp;{\r\n&nbsp;&nbsp;if&nbsp;(mCamera&nbsp;!=&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;Camera.Parameters&nbsp;parameters&nbsp;=&nbsp;mCamera.getParameters();\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(parameters.isZoomSupported())&nbsp;{\/\/\u5224\u65ad\u662f\u5426\u652f\u6301\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;maxZoom&nbsp;=&nbsp;parameters.getMaxZoom();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(maxZoom&nbsp;==&nbsp;0)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(zoomValue&nbsp;&amp;gt;&nbsp;maxZoom)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zoomValue&nbsp;=&nbsp;maxZoom;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters.setZoom(zoomValue);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mCamera.setParameters(parameters);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>Note: \u81f3\u6b64\u6211\u4eec\u5df2\u7ecf\u5b8c\u6210\u4e86\u5bf9\u6240\u6709\u4e8b\u4ef6\u7684\u76d1\u542c, \u770b\u5230\u8fd9\u91cc\u5927\u5bb6\u4e5f\u8bb8\u6709\u4e9b\u75b2\u60eb\u4e86, \u4e0d\u8fc7\u4e0d\u8981\u7070\u5fc3, \u73b0\u5728\u5b8c\u6210\u6211\u4eec\u7684\u6838\u5fc3\u90e8\u5206, \u5b9e\u73b0\u89c6\u9891\u7684\u5f55\u5236<\/p>\n<p><strong>\u5b9e\u73b0\u89c6\u9891\u7684\u5f55\u5236<\/strong><\/p>\n<p>\u8bf4\u662f\u6838\u5fc3\u529f\u80fd, \u4e5f\u53ea\u4e0d\u8fc7\u662f\u6211\u4eec\u4e0d\u77e5\u9053\u67d0\u4e9bAPI\u65b9\u6cd5\u7f62\u4e86, \u4e0b\u9762\u4ee3\u7801\u4e2d\u6211\u5df2\u7ecf\u52a0\u4e86\u8be6\u7ec6\u7684\u6ce8\u91ca, \u90e8\u5206\u4e0d\u80fd\u7406\u89e3\u7684\u8bb0\u4f4f\u5c31\u597d^v^<\/p>\n<p><\/p>\n<pre>\/**\r\n&nbsp;*&nbsp;\u5f00\u59cb\u5f55\u5236\r\n&nbsp;*\/\r\nprivate&nbsp;void&nbsp;startRecord()&nbsp;{\r\n&nbsp;&nbsp;if&nbsp;(mMediaRecorder&nbsp;!=&nbsp;null)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u6ca1\u6709\u5916\u7f6e\u5b58\u50a8,&nbsp;\u76f4\u63a5\u505c\u6b62\u5f55\u5236\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/mMediaRecorder.reset();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mCamera.unlock();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setCamera(mCamera);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u4ece\u76f8\u673a\u91c7\u96c6\u89c6\u9891\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/&nbsp;\u4ece\u9ea6\u514b\u91c7\u96c6\u97f3\u9891\u4fe1\u606f\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/&nbsp;TODO:&nbsp;2016\/10\/20&nbsp;\u8bbe\u7f6e\u89c6\u9891\u683c\u5f0f\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setVideoSize(videoWidth,&nbsp;videoHeight);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u6bcf\u79d2\u7684\u5e27\u6570\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setVideoFrameRate(24);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u7f16\u7801\u683c\u5f0f\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/&nbsp;\u8bbe\u7f6e\u5e27\u9891\u7387\uff0c\u7136\u540e\u5c31\u6e05\u6670\u4e86\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setVideoEncodingBitRate(1&nbsp;*&nbsp;1024&nbsp;*&nbsp;1024&nbsp;*&nbsp;100);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/&nbsp;TODO:&nbsp;2016\/10\/20&nbsp;\u4e34\u65f6\u5199\u4e2a\u6587\u4ef6\u5730\u5740,&nbsp;\u7a0d\u5019\u8be5!!!\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;targetDir&nbsp;=&nbsp;Environment.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mTargetFile&nbsp;=&nbsp;new&nbsp;File(targetDir,\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SystemClock.currentThreadTimeMillis()&nbsp;+&nbsp;\".mp4\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setOutputFile(mTargetFile.getAbsolutePath());\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.prepare();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u6b63\u5f0f\u5f55\u5236\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.start();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isRecording&nbsp;=&nbsp;true;\r\n&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;}\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p><strong>\u5b9e\u73b0\u89c6\u9891\u7684\u505c\u6b62<\/strong><\/p>\n<p>\u5927\u5bb6\u53ef\u80fd\u4f1a\u95ee, \u89c6\u9891\u7684\u505c\u6b62\u4e3a\u4ec0\u4e48\u5355\u72ec\u62bd\u51fa\u6765\u8bf4\u5462? \u4ed4\u7ec6\u7684\u540c\u5b66\u770b\u4e0a\u9762\u4ee3\u7801\u4f1a\u770b\u5230\u8fd9\u4e24\u4e2a\u65b9\u6cd5: stopRecordSave\u548cstopRecordUnSave, \u4e00\u4e2a\u505c\u6b62\u4fdd\u5b58, \u4e00\u4e2a\u662f\u505c\u6b62\u4e0d\u4fdd\u5b58, \u63a5\u4e0b\u6765\u6211\u4eec\u5c31\u8865\u4e0a\u8fd9\u4e2a\u5751<\/p>\n<p><strong>\u505c\u6b62\u5e76\u4fdd\u5b58<\/strong><\/p>\n<p><\/p>\n<pre>private&nbsp;void&nbsp;stopRecordSave()&nbsp;{\r\n&nbsp;&nbsp;if&nbsp;(isRecording)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;isRunning&nbsp;=&nbsp;false;\r\n&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.stop();\r\n&nbsp;&nbsp;&nbsp;&nbsp;isRecording&nbsp;=&nbsp;false;\r\n&nbsp;&nbsp;&nbsp;&nbsp;Toast.makeText(this,&nbsp;\"\u89c6\u9891\u5df2\u7ecf\u653e\u81f3\"&nbsp;+&nbsp;mTargetFile.getAbsolutePath(),&nbsp;Toast.LENGTH_SHORT).show();\r\n&nbsp;&nbsp;}\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p><strong>\u505c\u6b62\u4e0d\u4fdd\u5b58<\/strong><\/p>\n<p><\/p>\n<pre>private&nbsp;void&nbsp;stopRecordUnSave()&nbsp;{\r\n&nbsp;&nbsp;if&nbsp;(isRecording)&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;isRunning&nbsp;=&nbsp;false;\r\n&nbsp;&nbsp;&nbsp;&nbsp;mMediaRecorder.stop();\r\n&nbsp;&nbsp;&nbsp;&nbsp;isRecording&nbsp;=&nbsp;false;\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(mTargetFile.exists())&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u4e0d\u4fdd\u5b58\u76f4\u63a5\u5220\u6389\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mTargetFile.delete();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>Note: \u8fd9\u4e2a\u505c\u6b62\u4e0d\u4fdd\u5b58\u662f\u6211\u81ea\u5df1\u7684\u4e00\u79cd\u60f3\u6cd5, \u5982\u679c\u5927\u5bb6\u6709\u66f4\u597d\u7684\u60f3\u6cd5, \u6b22\u8fce\u5927\u5bb6\u5230\u8bc4\u8bba\u4e2d\u6307\u51fa, \u4e0d\u80dc\u611f\u6fc0<\/p>\n<p>\u4ee5\u4e0a\u5c31\u662f\u4f7f\u7528Android\u5b9e\u73b0\u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u529f\u80fd\u8be6\u7ec6\u4ecb\u7ecd\u7684\u8be6\u7ec6\u5185\u5bb9\uff0c\u66f4\u591a\u8bf7\u5173\u6ce8\u7c73\u4e91\u5176\u5b83\u76f8\u5173\u6587\u7ae0\uff01<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8fd9\u7bc7\u6587\u7ae0\u4e3b\u8981\u4ecb\u7ecd\u4e86android \u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u529f\u80fd\u5b9e\u73b0\u8be6\u89e3\u7684\u76f8\u5173\u8d44\u6599,\u8fd9\u91cc\u63d0\u4f9b\u4e86\u5177\u4f53\u7684\u5b9e\u73b0\u601d\u8def\u53ca\u4ee3\u7801\uff0c\u9700\u8981\u7684\u670b\u53cb\u53ef\u4ee5\u53c2\u8003\u4e0b Android \u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u529f\u80fd \u5f00\u53d1\u4e4b\u524d \u8fd9\u51e0\u5929\u63a5\u89e6\u4e86\u4e00\u4e0b\u548c\u89c6\u9891\u76f8\u5173\u7684\u63a7\u4ef6, \u6240\u4ee5, \u7ee7\u4e4b\u524d\u7684\u5fae\u4fe1\u6447\u4e00\u6447, \u6211\u60f3\u5230\u4e86\u6765\u5b9e\u73b0\u4e00\u4e0b\u5fae\u4fe1\u5c0f\u89c6\u9891\u5f55\u5236\u7684\u529f\u80fd, \u5b83\u7684\u529f\u80fd\u70b9\u6bd4\u8f83\u591a, \u6211\u6bcf\u5929\u90fd\u62bd\u51fa\u70b9\u65f6\u95f4\u6765\u5199\u5199, \u8bf4\u5b9e\u8bdd, \u6709\u4e9b\u4e1c\u897f\u8fd8\u662f\u6bd4\u8f83\u8d39\u52b2, \u5e0c\u671b\u5927\u5bb6\u8ba4\u771f\u770b\u770b, \u8bf4\u5f97\u4e0d\u5bf9\u7684\u5730\u65b9\u8fd8\u8bf7\u5927\u5bb6\u5728\u8bc4\u8bba\u4e2d\u6307\u6b63. \u5e9f\u8bdd\u4e0d\u591a\u8bf4, \u8fdb\u5165\u6b63\u9898. \u5f00\u53d1\u73af\u5883 \u70b9\u51fb\u4e0b\u8f7d\u201c\u201d\uff1b \u6700\u8fd1\u521a\u66f4\u65b0\u7684, \u6ca1\u66f4\u65b0\u7684\u5c0f\u4f19\u4f34\u4eec\u6293\u7d27\u4e86 Android Studio 2.2.2 JDK1.7 API 24 Gradle 2.2.2 \u76f8\u5173\u77e5\u8bc6\u70b9 \u89c6\u9891\u5f55\u5236\u754c\u9762 SurfaceView \u7684\u4f7f\u7528 Camera\u7684\u4f7f\u7528 \u76f8\u673a\u7684\u5bf9\u7126, \u53d8\u7126 \u89c6\u9891\u5f55\u5236\u63a7\u4ef6MediaRecorder\u7684\u4f7f\u7528 \u7b80\u5355\u81ea\u5b9a\u4e49View GestureDetector(\u624b\u52bf\u68c0\u6d4b)\u7684\u4f7f\u7528 \u7528\u5230\u7684\u4e1c\u897f\u771f\u4e0d\u5c11, \u4e0d\u8fc7\u522b\u7740\u6025, \u54b1\u4eec\u4e00\u4e2a\u4e00\u4e2a\u6765. \u5f00\u59cb\u5f00\u53d1 \u6848\u4f8b\u5206\u6790 \u5927\u5bb6\u53ef\u4ee5\u6253\u5f00\u81ea\u5df1\u5fae\u4fe1\u91cc\u9762\u7684\u5c0f\u89c6\u9891, \u4e00\u5757\u7b80\u5355\u7684\u5206\u6790\u4e00\u4e0b\u5b83\u7684\u529f\u80fd\u70b9\u6709\u54ea\u4e9b ? \u57fa\u672c\u7684\u89c6\u9891\u9884\u89c8\u529f\u80fd \u957f\u6309 \u201c\u6309\u4f4f\u62cd\u201d \u5b9e\u73b0\u89c6\u9891\u7684\u5f55\u5236 \u5f55\u5236\u8fc7\u7a0b\u4e2d\u7684\u8fdb\u5ea6\u6761\u4ece\u4e24\u4fa7\u5411\u4e2d\u95f4\u53d8\u77ed \u5f53\u677e\u624b\u6216\u8005\u8fdb\u5ea6\u6761\u8d70\u5230\u5c3d\u5934\u89c6\u9891\u505c\u6b62\u5f55\u5236 \u5e76\u4fdd\u5b58 \u4ece [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[],"class_list":["post-29297","post","type-post","status-publish","format-standard","hentry","category-19"],"_links":{"self":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/29297","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/comments?post=29297"}],"version-history":[{"count":0,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/29297\/revisions"}],"wp:attachment":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/media?parent=29297"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/categories?post=29297"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/tags?post=29297"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}