list, String str) {
151 | for (String string : list) {
152 | if (string.equals(str.trim())) {
153 | return true;
154 | }
155 | }
156 | return false;
157 | }
158 |
159 | public static String getHost(String url) {
160 | if (url == null || url.trim().equals("")) {
161 | return "";
162 | }
163 | String host = "";
164 | String regex = "^(https?)://[-a-zA-Z0-9.:]+[-a-zA-Z0-9]";
165 | Pattern p = Pattern.compile(regex);
166 | Matcher matcher = p.matcher(url);
167 | if (matcher.find()) {
168 | host = matcher.group();
169 | }
170 | return host;
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/videocapture/VideoCapture.java:
--------------------------------------------------------------------------------
1 | package com.example.videocapture;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.media.MediaCodec;
6 | import android.media.MediaCodecInfo;
7 | import android.media.MediaFormat;
8 | import android.media.MediaMuxer;
9 | import android.util.Log;
10 | import android.view.Surface;
11 |
12 | import com.googlecode.javacv.FFmpegFrameRecorder;
13 | import com.googlecode.javacv.FrameRecorder.Exception;
14 | import com.googlecode.javacv.cpp.opencv_core.IplImage;
15 |
16 | import java.io.IOException;
17 | import java.nio.ByteBuffer;
18 |
19 | /**
20 | * Created by zhangzhaolei on 15-6-30.
21 | */
22 |
23 | public class VideoCapture {
24 | private final String TAG = "VideoCapture";
25 |
26 | private int encodeMethod = 0; // 0 - MediaCodec; 1 - FFmepgFrameRecorder
27 |
28 | // var for encode method 0
29 | private static final String MIME_TYPE = "video/avc";
30 | private static final int BIT_RATE = 400000;
31 | private static final int FRAMES_PER_SECOND = 20;
32 | private static final int IFRAME_INTERVAL = 5;
33 |
34 | private MediaCodec.BufferInfo mBufferInfo;
35 | private MediaCodec mEncoder;
36 | private MediaMuxer mMuxer;
37 | private Surface mInputSurface;
38 | private int mTrackIndex;
39 | private boolean mMuxerStarted;
40 | private long mFakePts;
41 |
42 |
43 | // var for encode method 1
44 | private FFmpegFrameRecorder recorder;
45 | private IplImage newin;
46 |
47 |
48 | public void start(String pathName, int width, int height) {
49 | Log.d(TAG, "pathName=" + pathName + ", width=" + width + ", height=" + height);
50 | if (encodeMethod == 0) {
51 | prepareEncoder(pathName, width, height);
52 | } else {
53 | try {
54 | recorder = new FFmpegFrameRecorder(pathName, width, height);
55 | recorder.setFormat("mp4");
56 | recorder.setFrameRate(30f);
57 | recorder.start();
58 | } catch (Exception e) {
59 | Log.e(TAG, e.getMessage());
60 | }
61 | }
62 | }
63 |
64 | private void prepareEncoder(String pathName, int width, int height) {
65 | mBufferInfo = new MediaCodec.BufferInfo();
66 |
67 | MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
68 |
69 | // Set some properties. Failing to specify some of these can cause the MediaCodec
70 | // configure() call to throw an unhelpful exception.
71 | format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
72 | MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
73 | format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
74 | format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAMES_PER_SECOND);
75 | format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
76 | Log.d(TAG, "format: " + format);
77 |
78 | // Create a MediaCodec encoder, and configure it with our format. Get a Surface
79 | // we can use for input and wrap it with a class that handles the EGL work.
80 | try {
81 | mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
82 | } catch (IOException e) {
83 | e.printStackTrace();
84 | }
85 | mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
86 | mInputSurface = mEncoder.createInputSurface();
87 | mEncoder.start();
88 |
89 | // Create a MediaMuxer. We can't add the video track and start() the muxer here,
90 | // because our MediaFormat doesn't have the Magic Goodies. These can only be
91 | // obtained from the encoder after it has started processing data.
92 | //
93 | // We're not actually interested in multiplexing audio. We just want to convert
94 | // the raw H.264 elementary stream we get from MediaCodec into a .mp4 file.
95 | Log.d(TAG, "output will go to " + pathName);
96 | try {
97 | mMuxer = new MediaMuxer(pathName.toString(),
98 | MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
99 | } catch (IOException e) {
100 | e.printStackTrace();
101 | }
102 |
103 | mTrackIndex = -1;
104 | mMuxerStarted = false;
105 |
106 | }
107 | /**
108 | * Extracts all pending data from the encoder.
109 | *
110 | * If endOfStream is not set, this returns when there is no more data to drain. If it
111 | * is set, we send EOS to the encoder, and then iterate until we see EOS on the output.
112 | * Calling this with endOfStream set should be done once, right before stopping the muxer.
113 | */
114 | private void drainEncoder(boolean endOfStream) {
115 | final int TIMEOUT_USEC = 10000;
116 | Log.d(TAG, "drainEncoder(" + endOfStream + ")");
117 |
118 | if (endOfStream) {
119 | Log.d(TAG, "sending EOS to encoder");
120 | mEncoder.signalEndOfInputStream();
121 | }
122 |
123 | ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
124 | while (true) {
125 | int encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
126 | if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
127 | // no output available yet
128 | if (!endOfStream) {
129 | break; // out of while
130 | } else {
131 | Log.d(TAG, "no output available, spinning to await EOS");
132 | }
133 | } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
134 | // not expected for an encoder
135 | encoderOutputBuffers = mEncoder.getOutputBuffers();
136 | } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
137 | // should happen before receiving buffers, and should only happen once
138 | if (mMuxerStarted) {
139 | throw new RuntimeException("format changed twice");
140 | }
141 | MediaFormat newFormat = mEncoder.getOutputFormat();
142 | Log.d(TAG, "encoder output format changed: " + newFormat);
143 |
144 | // now that we have the Magic Goodies, start the muxer
145 | mTrackIndex = mMuxer.addTrack(newFormat);
146 | mMuxer.start();
147 | mMuxerStarted = true;
148 | } else if (encoderStatus < 0) {
149 | Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: " +
150 | encoderStatus);
151 | // let's ignore it
152 | } else {
153 | ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
154 | if (encodedData == null) {
155 | throw new RuntimeException("encoderOutputBuffer " + encoderStatus +
156 | " was null");
157 | }
158 |
159 | if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
160 | // The codec config data was pulled out and fed to the muxer when we got
161 | // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
162 | Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
163 | mBufferInfo.size = 0;
164 | }
165 |
166 | if (mBufferInfo.size != 0) {
167 | if (!mMuxerStarted) {
168 | throw new RuntimeException("muxer hasn't started");
169 | }
170 |
171 | // adjust the ByteBuffer values to match BufferInfo
172 | encodedData.position(mBufferInfo.offset);
173 | encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
174 | mBufferInfo.presentationTimeUs = mFakePts;
175 | mFakePts += 1000000L / FRAMES_PER_SECOND;
176 |
177 | mMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
178 | Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer");
179 | }
180 |
181 | mEncoder.releaseOutputBuffer(encoderStatus, false);
182 |
183 | if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
184 | if (!endOfStream) {
185 | Log.w(TAG, "reached end of stream unexpectedly");
186 | } else {
187 | Log.d(TAG, "end of stream reached");
188 | }
189 | break; // out of while
190 | }
191 | }
192 | }
193 | }
194 |
195 | /**
196 | * Generates a frame, writing to the Surface via the "software" API (lock/unlock).
197 | *
198 | * There's no way to set the time stamp.
199 | */
200 | private void generateFrame(Bitmap bmp) {
201 | Canvas canvas = mInputSurface.lockCanvas(null);
202 | try {
203 | if (canvas != null) {
204 | canvas.drawBitmap(bmp, 0, 0, null);
205 | }
206 | } finally {
207 | mInputSurface.unlockCanvasAndPost(canvas);
208 | }
209 | }
210 |
211 |
212 | /**
213 | * Releases encoder resources. May be called after partial / failed initialization.
214 | */
215 | private void releaseEncoder() {
216 | Log.d(TAG, "releasing encoder objects");
217 | if (mEncoder != null) {
218 | mEncoder.stop();
219 | mEncoder.release();
220 | mEncoder = null;
221 | }
222 | if (mInputSurface != null) {
223 | mInputSurface.release();
224 | mInputSurface = null;
225 | }
226 | if (mMuxer != null) {
227 | mMuxer.stop();
228 | mMuxer.release();
229 | mMuxer = null;
230 | }
231 | }
232 |
233 | public void record(Bitmap bmp) {
234 | if (encodeMethod == 0) {
235 | drainEncoder(false);
236 | generateFrame(bmp);
237 | } else {
238 | try {
239 | if (newin == null) {
240 | newin = IplImage.create(bmp.getWidth(), bmp.getHeight(), 8/*IPL_DEPTH_8U*/, 4);
241 | }
242 | bmp.copyPixelsToBuffer(newin.getByteBuffer());
243 | recorder.record(newin);
244 | } catch (Exception e) {
245 | Log.e(TAG, e.getMessage());
246 | }
247 | }
248 | }
249 |
250 | public void stop(){
251 | if (encodeMethod == 0) {
252 | drainEncoder(true);
253 | releaseEncoder();
254 | } else {
255 | try {
256 | recorder.stop();
257 | } catch (Exception e) {
258 | Log.e(TAG, e.getMessage());
259 | }
260 | }
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/videocapture/PhoneUtil.java.bak:
--------------------------------------------------------------------------------
1 | package info.smemo.wechatvideorecorder;
2 |
3 | import android.content.Context;
4 | import android.hardware.Sensor;
5 | import android.hardware.SensorManager;
6 | import android.location.Criteria;
7 | import android.location.Location;
8 | import android.location.LocationManager;
9 | import android.net.ConnectivityManager;
10 | import android.net.NetworkInfo;
11 | import android.net.wifi.WifiInfo;
12 | import android.net.wifi.WifiManager;
13 | import android.telephony.TelephonyManager;
14 | import android.telephony.cdma.CdmaCellLocation;
15 | import android.telephony.gsm.GsmCellLocation;
16 | import android.util.DisplayMetrics;
17 | import android.view.Display;
18 | import android.view.WindowManager;
19 | import java.util.List;
20 | import java.util.Locale;
21 |
22 | public class PhoneUtil {
23 |
24 |
25 | /**
26 | * 获取传感器列表 type name vendor
27 | *
28 | * @param context
29 | * @return
30 | */
31 | public static String getSensorList(Context context) {
32 | SensorManager mSensorManager = (SensorManager) context
33 | .getSystemService(Context.SENSOR_SERVICE);
34 | if(null == mSensorManager)
35 | return "";
36 | List sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
37 | StringBuilder builder = new StringBuilder();
38 | for (Sensor sensor : sensors)
39 | builder.append(sensor.getType() + "," + sensor.getName() + ","
40 | + sensor.getVendor() + "|");
41 | return builder.toString().substring(0, builder.toString().length() - 1);
42 | }
43 |
44 | public static boolean isOpenNetwork(Context context) {
45 | ConnectivityManager connManager = (ConnectivityManager) context
46 | .getSystemService(Context.CONNECTIVITY_SERVICE);
47 | if (connManager.getActiveNetworkInfo() != null) {
48 | return connManager.getActiveNetworkInfo().isAvailable();
49 | } else {
50 | return false;
51 | }
52 | }
53 |
54 | /**
55 | * WIFI是否连接
56 | *
57 | * @param context
58 | * @return
59 | */
60 | public static boolean isWifiConnected(Context context) {
61 | if (context != null) {
62 | ConnectivityManager mConnectivityManager = (ConnectivityManager) context
63 | .getSystemService(Context.CONNECTIVITY_SERVICE);
64 | NetworkInfo mWiFiNetworkInfo = mConnectivityManager
65 | .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
66 | if (mWiFiNetworkInfo != null) {
67 | return mWiFiNetworkInfo.isAvailable();
68 | }
69 | }
70 | return false;
71 | }
72 |
73 | public static float getDensity(Context context) {
74 | DisplayMetrics displayMetrics = context.getResources()
75 | .getDisplayMetrics();
76 | return displayMetrics.density;
77 | }
78 |
79 | /**
80 | * 获取当前手机的IMSI号
81 | */
82 | public static String getIMSI(Context context) {
83 | TelephonyManager telephonyManager = (TelephonyManager) context
84 | .getSystemService(Context.TELEPHONY_SERVICE);
85 | if(null == telephonyManager)
86 | return "";
87 | String imsi = telephonyManager.getSubscriberId();
88 | if(StringUtil.isEmpty(imsi))
89 | return "";
90 | return imsi;
91 | }
92 |
93 | /**
94 | * 获取当前手机的IMEI号
95 | */
96 | public static String getIMEI(Context context) {
97 | TelephonyManager telephonyManager = (TelephonyManager) context
98 | .getSystemService(Context.TELEPHONY_SERVICE);
99 | if(null == telephonyManager)
100 | return "";
101 | String id=telephonyManager.getDeviceId();
102 | if(StringUtil.isEmpty(id))
103 | return "";
104 | return telephonyManager.getDeviceId();
105 | }
106 |
107 | /**
108 | * 获取当前手机的Mac号
109 | */
110 | public static String getMac(Context context) {
111 | try {
112 | String macAddress = null;
113 | WifiManager wifiMgr = (WifiManager) context
114 | .getSystemService(Context.WIFI_SERVICE);
115 | WifiInfo info = (null == wifiMgr ? null : wifiMgr.getConnectionInfo());
116 | if (null != info) {
117 | macAddress = info.getMacAddress();
118 | if (StringUtil.isEmpty(macAddress))
119 | return "";
120 | macAddress = macAddress.replaceAll(":", "");
121 | macAddress = macAddress.toLowerCase(Locale.CHINA);
122 | return macAddress;
123 |
124 | }
125 | return "";
126 | }catch (Exception e){
127 | return "";
128 | }
129 | }
130 |
131 | /**
132 | * 获取当前手机当前wifi的SSID
133 | */
134 | public static String getSSIDWithContext(Context context) {
135 | WifiManager mWifi = (WifiManager) context
136 | .getSystemService(Context.WIFI_SERVICE);
137 | WifiInfo iWifi = mWifi.getConnectionInfo();
138 | if (null == iWifi)
139 | return "";
140 | String wifiName = iWifi.getSSID();
141 | if (StringUtil.isEmpty(wifiName))
142 | return "";
143 | return wifiName;
144 | }
145 |
146 | /**
147 | * 获取当前连接WIFI的mac地址
148 | *
149 | * @param context
150 | * @return
151 | */
152 | public static String getSSIDWithMac(Context context) {
153 | WifiManager mWifi = (WifiManager) context
154 | .getSystemService(Context.WIFI_SERVICE);
155 | WifiInfo iWifi = mWifi.getConnectionInfo();
156 | if (null == iWifi)
157 | return "";
158 | String mac = iWifi.getBSSID();
159 | if (StringUtil.isEmpty(mac))
160 | return "";
161 | mac = mac.replaceAll(":", "");
162 | mac = mac.toLowerCase(Locale.CHINA);
163 | return mac;
164 | }
165 |
166 | /**
167 | * 获取手机的信息提供商
168 | */
169 | public static String getPhoneType(Context context) {
170 | TelephonyManager telManager = (TelephonyManager) context
171 | .getSystemService(Context.TELEPHONY_SERVICE);
172 | String imsi = telManager.getSubscriberId();
173 | if (StringUtil.isEmpty(imsi))
174 | return "";
175 | if (imsi.startsWith("46000") || imsi.startsWith("46002")) {
176 | return "中国移动";
177 | } else if (imsi.startsWith("46001")) {
178 | return "中国联通";
179 | } else if (imsi.startsWith("46003")) {
180 | return "中国电信";
181 | } else {
182 | return "";
183 | }
184 | }
185 |
186 | /**
187 | * get resolution
188 | *
189 | * @param context
190 | * @return
191 | */
192 | public static int[] getResolution(Context context) {
193 | int resolution[] = new int[2];
194 | DisplayMetrics dm = new DisplayMetrics();
195 | PhoneManager.getWindowManger(context).getDefaultDisplay()
196 | .getMetrics(dm);
197 | resolution[0] = dm.widthPixels;
198 | resolution[1] = dm.heightPixels;
199 | return resolution;
200 | }
201 |
202 | /**
203 | * 判断是否为平板
204 | *
205 | * @return
206 | */
207 | public static boolean isPad(Context context) {
208 | WindowManager wm = PhoneManager.getWindowManger(context);
209 | Display display = wm.getDefaultDisplay();
210 | DisplayMetrics dm = new DisplayMetrics();
211 | display.getMetrics(dm);
212 | double x = Math.pow(dm.widthPixels / dm.xdpi, 2);
213 | double y = Math.pow(dm.heightPixels / dm.ydpi, 2);
214 | // 屏幕尺寸
215 | double screenInches = Math.sqrt(x + y);
216 | // 大于6尺寸则为Pad
217 | if (screenInches >= 6.0) {
218 | return true;
219 | }
220 | return false;
221 | }
222 |
223 | /**
224 | * 获取GPS经纬度坐标
225 | *
226 | * @param context
227 | * @return
228 | */
229 | public static String getGPSLocation(Context context) {
230 | double[] long_lat = new double[2];
231 | LocationManager locationManager = null;
232 | boolean gps = false;
233 | try {
234 | // A LocationManager for controlling location (e.g., GPS) updates.
235 | locationManager = PhoneManager.getLocationManager(context);
236 | if (null != locationManager)
237 | gps = locationManager
238 | .isProviderEnabled(LocationManager.GPS_PROVIDER);
239 | Criteria criteria = new Criteria();
240 | criteria.setAccuracy(Criteria.ACCURACY_FINE);// 高精度
241 | criteria.setAltitudeRequired(false);// 不要求海拔
242 | criteria.setBearingRequired(false);// 不要求方位
243 | criteria.setCostAllowed(true);// 允许有花费
244 | criteria.setPowerRequirement(Criteria.POWER_LOW);// 低功耗
245 | // 从可用的位置提供器中,匹配以上标准的最佳提供器
246 | String provider = locationManager.getBestProvider(criteria, true);
247 |
248 | // 获得最后一次变化的位置
249 | Location location = locationManager.getLastKnownLocation(provider);
250 | if (null == location) {
251 | return "::" + (gps ? 1 : 0);
252 | }
253 | long_lat[0] = location.getLongitude();
254 | long_lat[1] = location.getLatitude();
255 |
256 | } catch (Exception e) {
257 | return "error:" + e.toString();
258 | }
259 | return long_lat[0] + ":" + long_lat[1] + ":" + (gps ? 1 : 0);
260 | }
261 |
262 | public static String getGpsLongitude(Context context) {
263 | if (getGpsData(context) == null)
264 | return "";
265 | return String.valueOf(getGpsData(context)[0]);
266 | }
267 |
268 | public static String getGpsLatitude(Context context) {
269 | if (getGpsData(context) == null)
270 | return "";
271 | return String.valueOf(getGpsData(context)[1]);
272 | }
273 |
274 | public static double[] getGpsData(Context context) {
275 | double[] long_lat = new double[2];
276 | LocationManager locationManager = null;
277 | try {
278 | // A LocationManager for controlling location (e.g., GPS) updates.
279 | locationManager = PhoneManager.getLocationManager(context);
280 | Criteria criteria = new Criteria();
281 | criteria.setAccuracy(Criteria.ACCURACY_FINE);// 高精度
282 | criteria.setAltitudeRequired(false);// 不要求海拔
283 | criteria.setBearingRequired(false);// 不要求方位
284 | criteria.setCostAllowed(true);// 允许有花费
285 | criteria.setPowerRequirement(Criteria.POWER_LOW);// 低功耗
286 | // 从可用的位置提供器中,匹配以上标准的最佳提供器
287 | String provider = locationManager.getBestProvider(criteria, true);
288 |
289 | // 获得最后一次变化的位置
290 | Location location = locationManager.getLastKnownLocation(provider);
291 | if (null == location) {
292 | return null;
293 | }
294 | long_lat[0] = location.getLongitude();
295 | long_lat[1] = location.getLatitude();
296 |
297 | } catch (Exception e) {
298 | return null;
299 | }
300 |
301 | return long_lat;
302 | }
303 |
304 | /**
305 | * 获取基站坐标
306 | *
307 | * @param context
308 | * @return
309 | */
310 | public static String getLBSLocation(Context context) {
311 | /** 网络编号46000,46002编号(134/159号段):中国移动 46001:中国联通 46003:中国电信 */
312 | String simOper = "";
313 | /**
314 | * cid(GMS),lac(GMS),networkid=默认字段(GMS) cid:基站小区号(CDMA) lac:系统标识(CDMA)
315 | * networkid(CDMA)
316 | */
317 | /** 基站编码 */
318 | int cid = 0;
319 | /** 位置区域码 */
320 | int lac = 0;
321 | int networkid = 0;
322 |
323 | try {
324 | TelephonyManager tm = PhoneManager.getTelephonyManager(context);
325 | // SIM卡已准备好:SIM_STATE_READY=5
326 | if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
327 | // 取得SIM卡供货商代码,判断运营商是中国移动\中国联通\中国电信
328 | // 我国为460;中国移动为00,中国联通为01,中国电信为03
329 | simOper = tm.getSimOperator();
330 | /**
331 | * 获取网络类型 NETWORK_TYPE_CDMA 网络类型为CDMA NETWORK_TYPE_EDGE
332 | * 网络类型为EDGE NETWORK_TYPE_EVDO_0 网络类型为EVDO0 NETWORK_TYPE_EVDO_A
333 | * 网络类型为EVDOA NETWORK_TYPE_GPRS 网络类型为GPRS NETWORK_TYPE_HSDPA
334 | * 网络类型为HSDPA NETWORK_TYPE_HSPA 网络类型为HSPA NETWORK_TYPE_HSUPA
335 | * 网络类型为HSUPA NETWORK_TYPE_UMTS 网络类型为UMTS
336 | *
337 | * 在中国,联通的3G为UMTS或HSDPA,移动和联通的2G为GPRS或EGDE,电信的2G为CDMA,电信的3G为EVDO
338 | */
339 | int type = tm.getNetworkType();
340 | if (type == TelephonyManager.PHONE_TYPE_GSM // GSM网
341 | || type == TelephonyManager.NETWORK_TYPE_EDGE
342 | || type == TelephonyManager.NETWORK_TYPE_HSDPA) {
343 |
344 | GsmCellLocation gsm = ((GsmCellLocation) tm
345 | .getCellLocation());
346 | if (gsm != null) {
347 | // 取得SIM卡供货商代码,判断运营商是中国移动\中国联通\中国电信
348 | // 我国为460;中国移动为00,中国联通为01,中国电信为03
349 | simOper = tm.getSimOperator();
350 | // 基站ID
351 | cid = gsm.getCid();
352 | // 区域码
353 | lac = gsm.getLac();
354 |
355 | networkid = 0;
356 | } else {
357 |
358 | }
359 | } else if (type == TelephonyManager.NETWORK_TYPE_CDMA // 电信cdma网
360 | || type == TelephonyManager.NETWORK_TYPE_1xRTT
361 | || type == TelephonyManager.NETWORK_TYPE_EVDO_0
362 | || type == TelephonyManager.NETWORK_TYPE_EVDO_A) {
363 |
364 | CdmaCellLocation cdma = (CdmaCellLocation) tm
365 | .getCellLocation();
366 | if (cdma != null) {
367 | // 运营商1
368 | String mcc = tm.getNetworkOperator().substring(0, 3);
369 | // 运营商2
370 | String mnc = String.valueOf(cdma.getSystemId());
371 | simOper = mcc + mnc;
372 | // 基站ID
373 | cid = cdma.getBaseStationId();
374 | // 区域码
375 | lac = cdma.getSystemId();
376 |
377 | networkid = cdma.getNetworkId();
378 | } else {
379 |
380 | }
381 | }
382 | }
383 | } catch (Exception e) {
384 | return "";
385 | }
386 | return simOper + ":" + cid + ":" + lac + ":" + networkid;
387 | }
388 |
389 | }
390 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/videocapture/VideoRecordActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.videocapture;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Activity;
5 | import android.app.AlertDialog;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.util.DisplayMetrics;
9 | import android.util.Log;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.view.animation.AlphaAnimation;
14 | import android.view.animation.Animation;
15 | import android.view.animation.AnimationSet;
16 | import android.view.animation.ScaleAnimation;
17 | import android.widget.Button;
18 | import android.widget.TextView;
19 | import android.widget.Toast;
20 |
21 | import com.example.videocapture.http.HttpMultipartPost;
22 |
23 | import java.io.BufferedReader;
24 | import java.io.DataOutputStream;
25 | import java.io.File;
26 | import java.io.FileInputStream;
27 | import java.io.InputStream;
28 | import java.io.InputStreamReader;
29 | import java.net.HttpURLConnection;
30 | import java.net.URL;
31 |
32 | /**
33 | * Created by zhangzhaolei on 2015/6/30.
34 | */
35 |
36 | public class VideoRecordActivity extends Activity {
37 |
38 | private final static String TAG = "VideoRecordActivity";
39 | private VideoRecorderView recoderView;
40 | private Button videoController;
41 | private TextView message;
42 | private boolean isCancel = false;
43 | private HttpMultipartPost post;
44 |
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 |
50 | setContentView(R.layout.activity_record);
51 |
52 | recoderView = (VideoRecorderView) findViewById(R.id.recoder);
53 | videoController = (Button) findViewById(R.id.videoController);
54 | message = (TextView) findViewById(R.id.message);
55 |
56 | ViewGroup.LayoutParams params = recoderView.getLayoutParams();
57 | int[] dev = getDisplayMetrics();//PhoneUtil.getResolution(this);
58 | params.width = dev[0];
59 | params.height = dev[1]*2/3;//(int) (((float) dev[1])*4/5);
60 | recoderView.setLayoutParams(params);
61 | videoController.setOnTouchListener(new VideoTouchListener());
62 |
63 | recoderView.setRecorderListener(new VideoRecorderView.RecorderListener() {
64 |
65 | @Override
66 | public void recording(int maxtime, int nowtime) {
67 |
68 | }
69 |
70 | @SuppressLint("LongLogTag")
71 | @Override
72 | public void recordSuccess(File videoFile) {
73 | //System.out.println("recordSuccess");
74 | if (videoFile != null)
75 | Log.e(TAG+".recordSuccess()","videoFilePath======"+videoFile.getAbsolutePath());
76 | if (videoFile.getAbsolutePath() != null) {
77 | showDialog(videoFile.getAbsolutePath());
78 | }
79 | }
80 |
81 | @SuppressLint("LongLogTag")
82 | @Override
83 | public void recordStop() {
84 | Log.e(TAG+".recordStop()","=========");
85 | }
86 |
87 | @SuppressLint("LongLogTag")
88 | @Override
89 | public void recordCancel() {
90 | Log.e(TAG+".recordCancel()","=========");
91 | releaseAnimations();
92 | }
93 |
94 | @SuppressLint("LongLogTag")
95 | @Override
96 | public void recordStart() {
97 | Log.e(TAG+".recordStart()","=========");
98 | }
99 |
100 | @SuppressLint("LongLogTag")
101 | @Override
102 | public void videoStop() {
103 | Log.e(TAG+".videoStop()","=========");
104 | }
105 |
106 | @SuppressLint("LongLogTag")
107 | @Override
108 | public void videoStart() {
109 | Log.e(TAG+".videoStart()","=========");
110 | }
111 |
112 |
113 | });
114 |
115 | }
116 |
117 | @SuppressLint("LongLogTag")
118 | protected void showDialog(final String path) {
119 | AlertDialog.Builder builder = new AlertDialog.Builder(VideoRecordActivity.this);
120 | builder.setMessage("上传到服务器?");
121 | builder.setTitle("提示");
122 | builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
123 | @Override
124 | public void onClick(DialogInterface dialog, int which) {
125 | dialog.dismiss();
126 | Log.e(TAG+".showDialog()","path===="+path);
127 | Upload(path);
128 | //uploadFile(path);
129 | /*
130 | Intent intentPath = new Intent();
131 | intentPath.setClass(VideoRecordActivity.this,UploadActivity.class);
132 | intentPath.putExtra("path",path);
133 | //startActivity(new Intent(VideoRecordActivity.this, UploadActivity.class));
134 | startActivity(intentPath);
135 | */
136 | }
137 | });
138 | builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
139 | @Override
140 | public void onClick(DialogInterface dialog, int which) {
141 | dialog.dismiss();
142 | }
143 | });
144 | builder.create().show();
145 | }
146 |
147 | public void Upload (String videoPath){
148 | //String filePath = videoPath;//"/system/build.prop";
149 | File file = new File(videoPath);
150 | if (file.exists()) {
151 | post = new HttpMultipartPost(this, videoPath);
152 | post.execute();
153 | } else {
154 | Toast.makeText(this, "file not exists", Toast.LENGTH_LONG).show();
155 | finish();
156 | }
157 | }
158 |
159 | private void uploadFile(String path) {
160 |
161 | String uploadUrl = "http://192.168.1.228:8080/temp";
162 | String end = "\r\n";
163 | String twoHyphens = "--";
164 | String boundary = "******";
165 | try {
166 | URL url = new URL(uploadUrl);
167 | HttpURLConnection httpURLConnection = (HttpURLConnection) url
168 | .openConnection();
169 | httpURLConnection.setChunkedStreamingMode(128 * 1024);// 128K
170 | httpURLConnection.setDoInput(true);
171 | httpURLConnection.setDoOutput(true);
172 | httpURLConnection.setUseCaches(false);
173 | httpURLConnection.setRequestMethod("POST");
174 | httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
175 | httpURLConnection.setRequestProperty("Charset", "UTF-8");
176 | httpURLConnection.setRequestProperty("Content-Type",
177 | "multipart/form-data;boundary=" + boundary);
178 |
179 | DataOutputStream dos = new DataOutputStream(httpURLConnection
180 | .getOutputStream());
181 | dos.writeBytes(twoHyphens + boundary + end);
182 | dos
183 | .writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\""
184 | + path.substring(path.lastIndexOf("/") + 1)
185 | + "\"" + end);
186 | dos.writeBytes(end);
187 |
188 | FileInputStream fis = new FileInputStream(path);
189 | byte[] buffer = new byte[8192]; // 8k
190 | int count = 0;
191 | while ((count = fis.read(buffer)) != -1) {
192 | dos.write(buffer, 0, count);
193 |
194 | }
195 | fis.close();
196 |
197 | dos.writeBytes(end);
198 | dos.writeBytes(twoHyphens + boundary + twoHyphens + end);
199 | dos.flush();
200 |
201 | InputStream is = httpURLConnection.getInputStream();
202 | InputStreamReader isr = new InputStreamReader(is, "utf-8");
203 | BufferedReader br = new BufferedReader(isr);
204 | String result = br.readLine();
205 |
206 | Toast.makeText(this, result, Toast.LENGTH_LONG).show();
207 | dos.close();
208 | is.close();
209 |
210 | } catch (Exception e) {
211 | e.printStackTrace();
212 | setTitle(e.getMessage());
213 | }
214 |
215 | }
216 |
217 | public class VideoTouchListener implements View.OnTouchListener {
218 |
219 | @Override
220 | public boolean onTouch(View v, MotionEvent event) {
221 |
222 |
223 | switch (event.getAction()) {
224 | case MotionEvent.ACTION_DOWN:
225 | recoderView.startRecord();
226 | isCancel = false;
227 | pressAnimations();
228 | holdAnimations();
229 | break;
230 | case MotionEvent.ACTION_MOVE:
231 | if (event.getX() > 0
232 | && event.getX() < videoController.getWidth()
233 | && event.getY() > 0
234 | && event.getY() < videoController.getHeight()) {
235 | //showPressMessage();
236 | isCancel = false;
237 | } else {
238 | //cancelAnimations();
239 | isCancel = true;
240 | }
241 | break;
242 | case MotionEvent.ACTION_UP:
243 | if (isCancel) {
244 | recoderView.cancelRecord();
245 | }else{
246 | recoderView.endRecord();
247 | }
248 | message.setVisibility(View.GONE);
249 | releaseAnimations();
250 | break;
251 | default:
252 | break;
253 | }
254 | return false;
255 | }
256 | }
257 |
258 | /**
259 | * 移动取消弹出动画
260 | */
261 | /*
262 | public void cancelAnimations() {
263 | message.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light));
264 | message.setTextColor(getResources().getColor(android.R.color.white));
265 | message.setText("松手取消");
266 | }*/
267 |
268 | /**
269 | * 显示提示信息
270 | */
271 | /*
272 | public void showPressMessage() {
273 | message.setVisibility(View.VISIBLE);
274 | message.setBackgroundColor(getResources().getColor(android.R.color.transparent));
275 | message.setTextColor(getResources().getColor(android.R.color.holo_green_light));
276 | message.setText("上移取消");
277 | }*/
278 |
279 |
280 | /**
281 | * 按下时候动画效果
282 | */
283 | public void pressAnimations() {
284 | AnimationSet animationSet = new AnimationSet(true);
285 | ScaleAnimation scaleAnimation = new ScaleAnimation(1, 1.5f,
286 | 1, 1.5f,
287 | Animation.RELATIVE_TO_SELF, 0.5f,
288 | Animation.RELATIVE_TO_SELF, 0.5f);
289 | scaleAnimation.setDuration(200);
290 |
291 | AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
292 | alphaAnimation.setDuration(200);
293 |
294 | animationSet.addAnimation(scaleAnimation);
295 | animationSet.addAnimation(alphaAnimation);
296 | animationSet.setFillAfter(true);
297 | //message.setText("松手完成");
298 | videoController.startAnimation(animationSet);
299 | }
300 |
301 | /**
302 | * 释放时候动画效果
303 | */
304 | public void releaseAnimations() {
305 | AnimationSet animationSet = new AnimationSet(true);
306 | ScaleAnimation scaleAnimation = new ScaleAnimation(1.5f, 1f,
307 | 1.5f, 1f,
308 | Animation.RELATIVE_TO_SELF, 0.5f,
309 | Animation.RELATIVE_TO_SELF, 0.5f);
310 | scaleAnimation.setDuration(200);
311 |
312 | AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
313 | alphaAnimation.setDuration(200);
314 |
315 | animationSet.addAnimation(scaleAnimation);
316 | animationSet.addAnimation(alphaAnimation);
317 | animationSet.setFillAfter(true);
318 |
319 | //message.setVisibility(View.GONE);
320 | videoController.setText("按住拍");
321 | videoController.startAnimation(animationSet);
322 | }
323 |
324 | public void holdAnimations() {
325 | AnimationSet animationSet = new AnimationSet(true);
326 | ScaleAnimation scaleAnimation = new ScaleAnimation(1.5f, 1f,
327 | 1.5f, 1f,
328 | Animation.RELATIVE_TO_SELF, 0.5f,
329 | Animation.RELATIVE_TO_SELF, 0.5f);
330 | scaleAnimation.setDuration(200);
331 |
332 | AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
333 | alphaAnimation.setDuration(200);
334 |
335 | animationSet.addAnimation(scaleAnimation);
336 | animationSet.addAnimation(alphaAnimation);
337 | animationSet.setFillAfter(true);
338 |
339 | videoController.setText("松手完成");
340 | videoController.startAnimation(animationSet);
341 | }
342 |
343 | /**
344 | * get resolution
345 | *
346 | * @return
347 | */
348 | @SuppressLint("LongLogTag")
349 | public int[] getDisplayMetrics() {
350 | int resolution[] = new int[2];
351 | DisplayMetrics dm = new DisplayMetrics();
352 | getWindowManager().getDefaultDisplay()
353 | .getMetrics(dm);
354 | resolution[0] = dm.widthPixels;
355 | resolution[1] = dm.heightPixels;
356 | Log.e(TAG+".getDisplayMetrics()","DisplayMetrics.width="+dm.widthPixels+"***DisplayMetrics.height=dm.heightPixels");
357 | return resolution;
358 | }
359 |
360 | }
361 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/videocapture/VideoRecorderView.java:
--------------------------------------------------------------------------------
1 | package com.example.videocapture;
2 |
3 | import android.content.Context;
4 | import android.hardware.Camera;
5 | import android.media.MediaCodec;
6 | import android.media.MediaPlayer;
7 | import android.media.MediaRecorder;
8 | import android.os.Environment;
9 | import android.os.Handler;
10 | import android.os.Message;
11 | import android.util.AttributeSet;
12 | import android.view.LayoutInflater;
13 | import android.view.SurfaceHolder;
14 | import android.view.SurfaceView;
15 | import android.view.View;
16 | import android.widget.ImageView;
17 | import android.widget.LinearLayout;
18 | import android.widget.ProgressBar;
19 |
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.util.Timer;
23 | import java.util.TimerTask;
24 |
25 | /**
26 | * Created by zhangzhaolei on 2015/6/30.
27 | */
28 |
29 | public class VideoRecorderView extends LinearLayout implements MediaRecorder.OnErrorListener {
30 |
31 | //视频展示
32 | private SurfaceView surfaceView;
33 | private SurfaceHolder surfaceHoler;
34 |
35 | private SurfaceView videoSurfaceView;
36 | private ImageView playVideo;
37 |
38 | //进度条
39 | private ProgressBar progressBar_left;
40 | private ProgressBar progressBar_right;
41 |
42 | //录制视频
43 | private MediaRecorder mediaRecorder;
44 | //摄像头
45 | private Camera camera;
46 | private Timer timer;
47 |
48 | //视频播放
49 | private MediaPlayer mediaPlayer;
50 |
51 | //时间限制
52 | private static final int recordMaxTime = 30;
53 | private int timeCount;
54 | //生成的文件
55 | private File vecordFile;
56 |
57 | private Context context;
58 |
59 | //正在录制
60 | private boolean isRecording = false;
61 | //录制成功
62 | private boolean isSuccess = false;
63 |
64 | private RecorderListener recorderListener;
65 | private MediaCodec.BufferInfo mBufferInfo;
66 |
67 | public VideoRecorderView(Context context) {
68 | super(context, null);
69 | this.context = context;
70 | }
71 |
72 | public VideoRecorderView(Context context, AttributeSet attrs) {
73 | super(context, attrs, 0);
74 | this.context = context;
75 | init();
76 | }
77 |
78 | public VideoRecorderView(Context context, AttributeSet attrs, int defStyleAttr) {
79 | super(context, attrs, defStyleAttr);
80 | this.context = context;
81 | }
82 |
83 | private void init() {
84 |
85 | LayoutInflater.from(context).inflate(R.layout.ui_recorder, this);
86 | surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
87 | videoSurfaceView = (SurfaceView) findViewById(R.id.playView);
88 | playVideo = (ImageView) findViewById(R.id.playVideo);
89 |
90 | progressBar_left = (ProgressBar) findViewById(R.id.progressBar_left);
91 | progressBar_right = (ProgressBar) findViewById(R.id.progressBar_right);
92 |
93 | progressBar_left.setMax(recordMaxTime * 20);
94 | progressBar_right.setMax(recordMaxTime * 20);
95 |
96 | progressBar_left.setProgress(recordMaxTime * 20);
97 |
98 | surfaceHoler = surfaceView.getHolder();
99 | surfaceHoler.addCallback(new CustomCallBack());
100 | //surfaceHoler.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
101 | surfaceHoler.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
102 |
103 | initCamera();
104 |
105 | playVideo.setOnClickListener(new OnClickListener() {
106 | @Override
107 | public void onClick(View v) {
108 | playVideo();
109 | }
110 | });
111 | }
112 |
113 | private class CustomCallBack implements SurfaceHolder.Callback {
114 |
115 | @Override
116 | public void surfaceCreated(SurfaceHolder holder) {
117 | initCamera();
118 | }
119 |
120 | @Override
121 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
122 |
123 | }
124 |
125 | @Override
126 | public void surfaceDestroyed(SurfaceHolder holder) {
127 | freeCameraResource();
128 | }
129 | }
130 |
131 |
132 | @Override
133 | public void onError(MediaRecorder mr, int what, int extra) {
134 | try {
135 | if (mr != null)
136 | mr.reset();
137 | } catch (Exception e) {
138 |
139 | }
140 | }
141 |
142 | /**
143 | * 初始化摄像头
144 | */
145 | private void initCamera() {
146 | if (camera != null)
147 | freeCameraResource();
148 | try {
149 | camera = Camera.open();
150 | } catch (Exception e) {
151 | e.printStackTrace();
152 | freeCameraResource();
153 | }
154 | if (camera == null)
155 | return;
156 |
157 | camera.setDisplayOrientation(90);
158 | camera.autoFocus(null);
159 | try {
160 | camera.setPreviewDisplay(surfaceHoler);
161 | } catch (IOException e) {
162 | e.printStackTrace();
163 | }
164 | camera.startPreview();
165 | camera.unlock();
166 | }
167 |
168 | /**
169 | * 初始化摄像头配置
170 | */
171 | private void initRecord() {
172 | mBufferInfo = new MediaCodec.BufferInfo();
173 | mediaRecorder = new MediaRecorder();
174 | mediaRecorder.reset();
175 | if (camera != null)
176 | mediaRecorder.setCamera(camera);
177 |
178 | mediaRecorder.setOnErrorListener(this);
179 | mediaRecorder.setPreviewDisplay(surfaceHoler.getSurface());
180 | mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
181 | mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
182 |
183 |
184 | mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
185 | mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
186 | mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
187 |
188 | mediaRecorder.setVideoSize(352, 288);
189 |
190 | // mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
191 | mediaRecorder.setVideoFrameRate(15);
192 | mediaRecorder.setVideoEncodingBitRate(1 * 1024 * 512);
193 | mediaRecorder.setOrientationHint(90);
194 |
195 | mediaRecorder.setMaxDuration(recordMaxTime * 1000);
196 | mediaRecorder.setOutputFile(vecordFile.getAbsolutePath());
197 | }
198 |
199 | private void prepareRecord() {
200 | try {
201 | mediaRecorder.prepare();
202 | mediaRecorder.start();
203 | } catch (IOException e) {
204 | e.printStackTrace();
205 | }
206 | }
207 |
208 | /**
209 | * 开始录制
210 | */
211 | public void startRecord() {
212 |
213 | //录制中
214 | if (isRecording)
215 | return;
216 | //创建文件
217 | createRecordDir();
218 |
219 | initCamera();
220 |
221 | videoSurfaceView.setVisibility(View.GONE);
222 | playVideo.setVisibility(View.GONE);
223 | surfaceView.setVisibility(View.VISIBLE);
224 |
225 | //初始化控件
226 | initRecord();
227 | prepareRecord();
228 | isRecording = true;
229 | if (recorderListener != null)
230 | recorderListener.recordStart();
231 | //10秒自动化结束
232 | timeCount = 0;
233 | timer = new Timer();
234 | timer.schedule(new TimerTask() {
235 | @Override
236 | public void run() {
237 | timeCount++;
238 | progressBar_left.setProgress(timeCount);
239 | progressBar_right.setProgress(recordMaxTime * 20 - timeCount);
240 | if (recorderListener != null)
241 | recorderListener.recording(recordMaxTime * 1000, timeCount * 50);
242 | if (timeCount == recordMaxTime * 20) {
243 | Message message = new Message();
244 | message.what = 1;
245 | handler.sendMessage(message);
246 | }
247 | }
248 | }, 0, 50);
249 | }
250 |
251 | Handler handler = new Handler() {
252 | @Override
253 | public void handleMessage(Message msg) {
254 | super.handleMessage(msg);
255 | if (msg.what == 1) {
256 | endRecord();
257 | }
258 | }
259 | };
260 |
261 | /**
262 | * 停止录制
263 | */
264 | public void endRecord() {
265 | if (!isRecording)
266 | return;
267 | isRecording = false;
268 | if (recorderListener != null) {
269 | recorderListener.recordStop();
270 | recorderListener.recordSuccess(vecordFile);
271 | }
272 | stopRecord();
273 | releaseRecord();
274 | freeCameraResource();
275 | videoSurfaceView.setVisibility(View.VISIBLE);
276 | playVideo.setVisibility(View.VISIBLE);
277 | }
278 |
279 | /**
280 | * 取消录制
281 | */
282 | public void cancelRecord() {
283 | videoSurfaceView.setVisibility(View.GONE);
284 | playVideo.setVisibility(View.GONE);
285 | surfaceView.setVisibility(View.VISIBLE);
286 | if (!isRecording)
287 | return;
288 | isRecording = false;
289 | stopRecord();
290 | releaseRecord();
291 | freeCameraResource();
292 | isRecording = false;
293 | if (vecordFile.exists())
294 | vecordFile.delete();
295 | if (recorderListener != null)
296 | recorderListener.recordCancel();
297 | initCamera();
298 | }
299 |
300 | /**
301 | * 停止录制
302 | */
303 | private void stopRecord() {
304 | progressBar_left.setProgress(recordMaxTime * 20);
305 | progressBar_right.setProgress(0);
306 |
307 | if (timer != null)
308 | timer.cancel();
309 | if (mediaRecorder != null) {
310 | // 设置后不会崩
311 | mediaRecorder.setOnErrorListener(null);
312 | mediaRecorder.setPreviewDisplay(null);
313 | try {
314 | mediaRecorder.stop();
315 | } catch (IllegalStateException e) {
316 | e.printStackTrace();
317 | } catch (RuntimeException e) {
318 | e.printStackTrace();
319 | } catch (Exception e) {
320 | e.printStackTrace();
321 | }
322 | }
323 | }
324 |
325 |
326 | public void destoryMediaPlayer() {
327 | if (mediaPlayer == null)
328 | return;
329 | mediaPlayer.setDisplay(null);
330 | mediaPlayer.reset();
331 | mediaPlayer.release();
332 | mediaPlayer = null;
333 | }
334 |
335 | /**
336 | * 播放视频
337 | */
338 | public void playVideo() {
339 | surfaceView.setVisibility(View.GONE);
340 | videoSurfaceView.setVisibility(View.VISIBLE);
341 | playVideo.setVisibility(View.GONE);
342 | mediaPlayer = new MediaPlayer();
343 | try {
344 | mediaPlayer.reset();
345 | mediaPlayer.setDataSource(vecordFile.getAbsolutePath());
346 | mediaPlayer.setDisplay(videoSurfaceView.getHolder());
347 | mediaPlayer.prepare();//缓冲
348 | mediaPlayer.start();
349 | } catch (Exception e) {
350 | e.printStackTrace();
351 | }
352 | if (recorderListener != null)
353 | recorderListener.videoStart();
354 | mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
355 | @Override
356 | public void onCompletion(MediaPlayer mp) {
357 | if (recorderListener != null)
358 | recorderListener.videoStop();
359 | playVideo.setVisibility(View.VISIBLE);
360 | }
361 | });
362 | }
363 |
364 | public RecorderListener getRecorderListener() {
365 | return recorderListener;
366 | }
367 |
368 | public void setRecorderListener(RecorderListener recorderListener) {
369 | this.recorderListener = recorderListener;
370 | }
371 |
372 | public SurfaceView getSurfaceView() {
373 |
374 | return surfaceView;
375 | }
376 |
377 | public void setSurfaceView(SurfaceView surfaceView) {
378 | this.surfaceView = surfaceView;
379 | }
380 |
381 | public MediaPlayer getMediaPlayer() {
382 | return mediaPlayer;
383 | }
384 |
385 | public interface RecorderListener {
386 |
387 | public void recording(int maxtime, int nowtime);
388 |
389 | public void recordSuccess(File videoFile);
390 |
391 | public void recordStop();
392 |
393 | public void recordCancel();
394 |
395 | public void recordStart();
396 |
397 | public void videoStop();
398 |
399 | public void videoStart();
400 | }
401 |
402 |
403 | /**
404 | * 创建视频文件
405 | */
406 | private void createRecordDir() {
407 | File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "WeChatVideoRecorder/");
408 | if (!sampleDir.exists()) {
409 | sampleDir.mkdirs();
410 | }
411 | File vecordDir = sampleDir;
412 | // 创建文件
413 | try {
414 | vecordFile = File.createTempFile("recording", ".mp4", vecordDir);//mp4格式
415 | } catch (IOException e) {
416 | }
417 | }
418 |
419 | /**
420 | * 释放资源
421 | */
422 | private void releaseRecord() {
423 | if (mediaRecorder != null) {
424 | mediaRecorder.setOnErrorListener(null);
425 | try {
426 | mediaRecorder.release();
427 | } catch (IllegalStateException e) {
428 | e.printStackTrace();
429 | } catch (Exception e) {
430 | e.printStackTrace();
431 | }
432 | }
433 | mediaRecorder = null;
434 | }
435 |
436 | /**
437 | * 释放摄像头资源
438 | */
439 | private void freeCameraResource() {
440 | if (null != camera) {
441 | camera.setPreviewCallback(null);
442 | camera.stopPreview();
443 | camera.lock();
444 | camera.release();
445 | camera = null;
446 | }
447 | }
448 | }
449 |
--------------------------------------------------------------------------------