├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── drawable
│ │ │ │ ├── ic_back_file_selector.xml
│ │ │ │ ├── ic_txt_file_selector.xml
│ │ │ │ ├── ic_movie_file_selector.xml
│ │ │ │ ├── ic_photo_file_selector.xml
│ │ │ │ ├── ic_folder_open_file_selector.xml
│ │ │ │ ├── ic_compro_file_selector.xml
│ │ │ │ ├── ic_music_file_selector.xml
│ │ │ │ └── ic_other_file_selector.xml
│ │ │ └── layout
│ │ │ │ ├── file_selector_dialog_item.xml
│ │ │ │ └── activity_main.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── gson8
│ │ │ │ └── myscreenshot
│ │ │ │ ├── fileselector
│ │ │ │ ├── utils
│ │ │ │ │ ├── FileSelectorConfig.java
│ │ │ │ │ ├── FileCompare.java
│ │ │ │ │ ├── FileType.java
│ │ │ │ │ ├── FileFilter.java
│ │ │ │ │ └── FileUtils.java
│ │ │ │ ├── config
│ │ │ │ │ └── FileConfig.java
│ │ │ │ └── dialog
│ │ │ │ │ └── FileDialog.java
│ │ │ │ ├── video
│ │ │ │ ├── DpiBean.java
│ │ │ │ ├── SpinnerAdapter.java
│ │ │ │ └── MyShoter.java
│ │ │ │ └── MainActivity.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── gson8
│ │ │ └── myscreenshot
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── gson8
│ │ └── myscreenshot
│ │ └── ApplicationTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── my
├── app.apk
└── art.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── README.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/my/app.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/my/app.apk
--------------------------------------------------------------------------------
/my/art.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/my/art.png
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MyScreenShot
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/syusuke/MyScreenShot/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .idea/
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/fileselector/utils/FileSelectorConfig.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.fileselector.utils;
2 |
3 |
4 | public class FileSelectorConfig
5 | {
6 | public static final String NAME = "name";
7 | public static final String ICON = "icon";
8 | public static final String PATH = "path";
9 | public static final String TYPE = "type";
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/test/java/com/gson8/myscreenshot/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_back_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/gson8/myscreenshot/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_txt_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_movie_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_photo_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_folder_open_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_compro_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_music_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/fileselector/utils/FileCompare.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.fileselector.utils;
2 |
3 | import java.util.Comparator;
4 | import java.util.HashMap;
5 |
6 | /**
7 | * 文件比较的类
8 | */
9 | public class FileCompare implements Comparator>
10 | {
11 | @Override
12 | public int compare(HashMap lhs, HashMap rhs)
13 | {
14 | String n1 = (String)lhs.get(FileSelectorConfig.NAME);
15 | String n2 = (String)rhs.get(FileSelectorConfig.NAME);
16 | return n1.toUpperCase().compareTo(n2.toUpperCase());
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_other_file_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in F:\AndroidSDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.3"
6 |
7 | defaultConfig {
8 | applicationId "com.gson8.myscreenshot"
9 | minSdkVersion 19
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.4.0'
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/fileselector/utils/FileType.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.fileselector.utils;
2 |
3 |
4 | public class FileType {
5 | public static final int AUDIO = 1;
6 | public static final int VIDEO = 2;
7 | public static final int IMAGE = 3;
8 | public static final int TEX = 4;
9 | public static final int OTHER = 5;
10 | public static final int FOLDER = 10;
11 | public static final int COMPRESSION = 14; //压缩文件
12 |
13 | public static final int FILE = 20;
14 |
15 | public static final int All = 100;
16 |
17 |
18 | public static final int UPTO = 30;
19 |
20 | public static final int selected = 10086;
21 | public static final int unselect = 10010;
22 | public static final int forbid = 10000;
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/video/DpiBean.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.video;
2 |
3 | /*
4 | * ScreenShot making by Syusuke/琴声悠扬 on 2016/5/31
5 | * E-Mail: Zyj7810@126.com
6 | * Package: gson8.com.vedioshot.bean.DpiBean
7 | * Description: null
8 | */
9 |
10 | public class DpiBean {
11 | private int width;
12 | private int height;
13 |
14 | public DpiBean(int width, int height) {
15 | this.width = width;
16 | this.height = height;
17 | }
18 |
19 | public int getWidth() {
20 | return width;
21 | }
22 |
23 | public void setWidth(int width) {
24 | this.width = width;
25 | }
26 |
27 | public int getHeight() {
28 | return height;
29 | }
30 |
31 | public void setHeight(int height) {
32 | this.height = height;
33 | }
34 |
35 | @Override
36 | public String toString() {
37 | return width + "x" + height;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/file_selector_dialog_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/fileselector/config/FileConfig.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.fileselector.config;
2 |
3 |
4 | import android.os.Environment;
5 |
6 | import com.gson8.myscreenshot.fileselector.utils.FileFilter;
7 |
8 | public class FileConfig {
9 | //public static final String FILE_CONFIG = "fileConfig";
10 |
11 | public static boolean showHiddenFiles = false;
12 | public static int filterModel = FileFilter.FILTER_NONE; //过滤文件
13 | public static String[] filter;
14 | public static boolean positiveFiter = true;
15 | //文件选择可以访问的最高路径,默认为"/"
16 | public static String rootPath = "/";
17 | //文件选择器的开始的路径,默认为"/"
18 | // public static String startPath = "/";
19 | public static String startPath = Environment.getExternalStorageDirectory() + "";
20 |
21 | //public static int selectType = FileType.All; //选择文件的种类:文件夹、文件、全部
22 |
23 |
24 | //public static final String SELECT = "select";
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Android >= 5.0(4.4 root )
2 |
3 | ## 屏幕录制视频
4 |
5 | ```java
6 | //in onCreate
7 | mMediaProjectionManager =
8 | (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
9 |
10 |
11 | //开始截图,这里系统会弹出权限确认窗口
12 | Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
13 | startActivityForResult(captureIntent, REQUEST_CODE);
14 |
15 | //
16 | @Override
17 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
18 | if(requestCode == REQUEST_CODE) {
19 | startShotNow(resultCode, data);
20 | }
21 | }
22 |
23 |
24 |
25 | mMediaProjection =
26 | mMediaProjectionManager.getMediaProjection(resultCode, data);
27 |
28 | if(mMediaProjection == null) {
29 | Log.e(TAG, "MediaProjection is null");
30 | return;
31 | }
32 |
33 | mFile = new File(getRandomFileName());
34 |
35 | Log.e(TAG, "startShotNow: " + mDpiSizeBean.getHeight() + " " + mBitRate + " " + mFps);
36 |
37 |
38 | mShoter = new MyShoter(mDpiSizeBean.getWidth(), mDpiSizeBean.getHeight(), mBitRate, 1,
39 | mFps, mMediaProjection, mFile.getAbsolutePath());
40 |
41 | new Thread(mShoter).start();
42 | mBtnShotStart.setText("停止录制");
43 |
44 | moveTaskToBack(true);
45 |
46 | ```
47 |
48 | ## [APK DEMO](my/app.apk)
49 |
50 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/video/SpinnerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.video;
2 |
3 | /*
4 | * ScreenShot making by Syusuke/琴声悠扬 on 2016/6/2
5 | * E-Mail: Zyj7810@126.com
6 | * Package: gson8.com.vedioshot.adapter.SpinnerAdapter
7 | * Description: null
8 | */
9 |
10 | import android.content.Context;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.BaseAdapter;
15 | import android.widget.TextView;
16 |
17 | public class SpinnerAdapter extends BaseAdapter {
18 |
19 | private Object[] obj;
20 | private Context mContext;
21 |
22 | public SpinnerAdapter(Context contexts, Object[] objects) {
23 | this.mContext = contexts;
24 | this.obj = objects;
25 | }
26 |
27 |
28 | @Override
29 | public int getCount() {
30 | return obj.length;
31 | }
32 |
33 | @Override
34 | public Object getItem(int position) {
35 | return obj[position];
36 | }
37 |
38 | @Override
39 | public long getItemId(int position) {
40 | return position;
41 | }
42 |
43 | @Override
44 | public View getView(int position, View convertView, ViewGroup parent) {
45 |
46 | ViewHolder holder;
47 | if(convertView == null) {
48 | convertView = LayoutInflater.from(mContext)
49 | .inflate(android.R.layout.simple_list_item_1, parent, false);
50 | holder = new ViewHolder();
51 | holder.tv = (TextView) convertView.findViewById(android.R.id.text1);
52 | convertView.setTag(holder);
53 | } else {
54 | holder = (ViewHolder) convertView.getTag();
55 | }
56 |
57 | holder.tv.setText(obj[position].toString());
58 |
59 | return convertView;
60 | }
61 |
62 |
63 | class ViewHolder {
64 | TextView tv;
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/fileselector/utils/FileFilter.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.fileselector.utils;
2 |
3 |
4 | import com.gson8.myscreenshot.fileselector.config.FileConfig;
5 |
6 | import java.io.Serializable;
7 |
8 | public class FileFilter implements Serializable {
9 | public static final int FILTER_IMAGE = 1;
10 | public static final int FILTER_TXT = 2;
11 | public static final int FILTER_AUDIO = 3;
12 | public static final int FILTER_VIDEO = 4;
13 | public static final int FILTER_CUSTOM = 10;
14 | public static final int FILTER_COMPROSSION = 16;
15 | public static final int FILTER_NONE = -1;
16 |
17 | public static final String[] IMAGE_FILTER = new String[]{"png", "jpg", "bmp", "gif"};
18 |
19 | public static final String[] TXT_FILTER = new String[]{"txt", "c", "cpp", "java", "xml"};
20 |
21 | public static final String[] AUDIO_FILTER =
22 | new String[]{"mp3", "m4a", "ogg", "flac", "ape", "aac"};
23 |
24 | public static final String[] VIDEO_FILTER = new String[]{"mp4", "avi", "flv", "rmvb", "mkv"};
25 |
26 | public static final String[] ZIP_FILTER = new String[]{"zip"};
27 |
28 | public static final String[] RAR_FILTER = new String[]{"rar"};
29 |
30 | /**
31 | * 过滤处理
32 | *
33 | * @param lastName 文件后缀名
34 | * @return 匹配成功:true
35 | */
36 | public static boolean doFilter(String lastName) {
37 | if(lastName == null)
38 | return false;
39 |
40 | int model = FileConfig.filterModel;
41 | String[] filter = null;
42 | switch(model) {
43 | case FILTER_AUDIO:
44 | filter = AUDIO_FILTER;
45 | break;
46 | case FILTER_IMAGE:
47 | filter = IMAGE_FILTER;
48 | break;
49 | case FILTER_TXT:
50 | filter = TXT_FILTER;
51 | break;
52 | case FILTER_VIDEO:
53 | filter = VIDEO_FILTER;
54 | break;
55 | case FILTER_COMPROSSION:
56 | filter = ZIP_FILTER;
57 | break;
58 | default:
59 | filter = FileConfig.filter;
60 | break;
61 | }
62 |
63 | for(String f : filter) {
64 | if(f.equals(lastName))
65 | return true;
66 | }
67 |
68 | return false;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
18 |
22 |
23 |
30 |
31 |
39 |
40 |
41 |
45 |
46 |
53 |
54 |
62 |
63 |
64 |
65 |
69 |
70 |
77 |
78 |
86 |
87 |
88 |
89 |
95 |
96 |
102 |
103 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/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 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/fileselector/dialog/FileDialog.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.fileselector.dialog;
2 |
3 | /*
4 | * MyScreenShot making by Syusuke/琴声悠扬 on 2016/6/7
5 | * E-Mail: Zyj7810@126.com
6 | * Package: com.gson8.myscreenshot.fileselector.dialog.FileDialog
7 | * Description: null
8 | */
9 |
10 | import android.content.Context;
11 | import android.content.DialogInterface;
12 | import android.support.v7.app.AlertDialog;
13 | import android.view.LayoutInflater;
14 | import android.view.View;
15 | import android.view.ViewGroup;
16 | import android.widget.AdapterView;
17 | import android.widget.BaseAdapter;
18 | import android.widget.ImageView;
19 | import android.widget.ListView;
20 | import android.widget.TextView;
21 | import android.widget.Toast;
22 |
23 | import com.gson8.myscreenshot.R;
24 | import com.gson8.myscreenshot.fileselector.config.FileConfig;
25 | import com.gson8.myscreenshot.fileselector.utils.FileSelectorConfig;
26 | import com.gson8.myscreenshot.fileselector.utils.FileType;
27 | import com.gson8.myscreenshot.fileselector.utils.FileUtils;
28 |
29 | import java.util.ArrayList;
30 | import java.util.HashMap;
31 | import java.util.List;
32 |
33 | public class FileDialog {
34 |
35 | Context mContext;
36 | FileConfig mFileConfig;
37 |
38 | AlertDialog mDialog;
39 | AlertDialog.Builder builder;
40 | ListView listView;
41 | SelectFileDialogAdapter adapter;
42 | List> mFiles;
43 |
44 | int prePosition = 0;
45 |
46 | OnFileSelectFinish mOnFileSelectFinish;
47 |
48 | public FileDialog(Context mContext, FileConfig mFileConfig) {
49 | this.mContext = mContext;
50 | this.mFileConfig = mFileConfig;
51 |
52 | builder = new AlertDialog.Builder(mContext);
53 | builder.setTitle("选择文件");
54 | builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
55 | @Override
56 | public void onClick(DialogInterface dialog, int which) {
57 | dimissDialog();
58 | }
59 | });
60 | listView = new ListView(mContext);
61 | mFiles = new ArrayList<>();
62 | adapter = new SelectFileDialogAdapter();
63 | listView.setAdapter(adapter);
64 | listView.setOnItemClickListener(listviewItemClickListener);
65 | updateListView(FileConfig.startPath);
66 | }
67 |
68 |
69 | AdapterView.OnItemClickListener listviewItemClickListener =
70 | new AdapterView.OnItemClickListener() {
71 | @Override
72 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
73 | String path = (String) mFiles.get(position).get(FileSelectorConfig.PATH);
74 | if(path == null)
75 | return;
76 | int type = (int) mFiles.get(position).get(FileSelectorConfig.TYPE);
77 | switch(type) {
78 | case FileType.FOLDER:
79 | updateListView(path);
80 | listView.setSelection(0);
81 | prePosition = position;
82 | break;
83 | case FileType.FILE:
84 | if(mOnFileSelectFinish != null) {
85 | mOnFileSelectFinish.onFinishSelected(path);
86 | }
87 | dimissDialog();
88 | break;
89 | case FileType.UPTO:
90 | String parentPath = FileUtils.getParentPath(path);
91 | updateListView(parentPath);
92 | listView.setSelection(prePosition - 3);
93 | break;
94 | }
95 | }
96 | };
97 |
98 | private void updateListView(String path) {
99 | ArrayList> temp = null;
100 | try {
101 | temp = FileUtils.getFileList(path);
102 | } catch(Exception e) {
103 | e.printStackTrace();
104 | Toast.makeText(mContext, "打开失败", Toast.LENGTH_SHORT).show();
105 | return;
106 | }
107 | mFiles.clear();
108 | mFiles.addAll(temp);
109 |
110 | adapter.notifyDataSetChanged();
111 | //fileShowListView.setSelection(0);
112 | }
113 |
114 | public void showDialog() {
115 |
116 | mDialog = builder.create();
117 | mDialog.show();
118 | }
119 |
120 | public void dimissDialog() {
121 | if(mDialog == null)
122 | throw new RuntimeException("没有初始化");
123 | mDialog.dismiss();
124 | }
125 |
126 | class SelectFileDialogAdapter extends BaseAdapter {
127 |
128 | @Override
129 | public int getCount() {
130 | return mFiles.size();
131 | }
132 |
133 | @Override
134 | public Object getItem(int position) {
135 | return mFiles.get(position);
136 | }
137 |
138 | @Override
139 | public long getItemId(int position) {
140 | return position;
141 | }
142 |
143 | @Override
144 | public View getView(int position, View convertView, ViewGroup parent) {
145 |
146 | ViewHolder holder;
147 | if(convertView == null) {
148 | convertView = LayoutInflater.from(mContext)
149 | .inflate(R.layout.file_selector_dialog_item, parent, false);
150 |
151 | holder = new ViewHolder();
152 | holder.icon = (ImageView) convertView.findViewById(R.id.file_selector_item_icon);
153 | holder.text = (TextView) convertView.findViewById(R.id.file_selector_item_text);
154 | convertView.setTag(holder);
155 | } else {
156 | holder = (ViewHolder) convertView.getTag();
157 | }
158 |
159 | String name = mFiles.get(position).get(FileSelectorConfig.NAME).toString();
160 | int icon = (int) mFiles.get(position).get(FileSelectorConfig.ICON);
161 |
162 | if(name != null) {
163 | holder.text.setText(name);
164 | }
165 |
166 | if(icon != 0) {
167 | holder.icon.setImageResource(icon);
168 | }
169 |
170 | return convertView;
171 | }
172 |
173 | class ViewHolder {
174 | ImageView icon;
175 | TextView text;
176 | }
177 | }
178 |
179 |
180 | public void setOnFileSelectFinish(OnFileSelectFinish mOnFileSelectFinish) {
181 | this.mOnFileSelectFinish = mOnFileSelectFinish;
182 | }
183 |
184 | public interface OnFileSelectFinish {
185 | void onFinishSelected(String path);
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/video/MyShoter.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.video;
2 |
3 | /*
4 | * ScreenShot making by Syusuke/琴声悠扬 on 2016/5/31
5 | * E-Mail: Zyj7810@126.com
6 | * Package: gson8.com.vedioshot.shots.MyShoter
7 | * Description: null
8 | */
9 |
10 | import android.hardware.display.DisplayManager;
11 | import android.hardware.display.VirtualDisplay;
12 | import android.media.MediaCodec;
13 | import android.media.MediaCodecInfo;
14 | import android.media.MediaFormat;
15 | import android.media.MediaMuxer;
16 | import android.media.projection.MediaProjection;
17 | import android.os.SystemClock;
18 | import android.util.Log;
19 | import android.view.Surface;
20 |
21 | import java.io.IOException;
22 | import java.nio.ByteBuffer;
23 | import java.util.concurrent.atomic.AtomicBoolean;
24 |
25 | public class MyShoter implements Runnable {
26 |
27 | private static final String TAG = MyShoter.class.getSimpleName();
28 |
29 | private static final String VIDEO_MIME_TYPE = "video/avc";
30 | private static final int IFRAME_INTERVAL = 10;
31 | private static final int TIMEOUT_US = 10000;
32 |
33 |
34 | /**
35 | * 录制的分辨率
36 | */
37 | private int mWidth;
38 | private int mHeight;
39 |
40 | /**
41 | * 录制的比特率
42 | */
43 | private int mBitRate;
44 |
45 | /**
46 | * 录制的帧数
47 | */
48 | private int mFrameRate; // 30 FPS
49 |
50 | /**
51 | * 这个数传 1 就可以
52 | */
53 | private int mDpi;
54 |
55 | /**
56 | * 文件保存路径
57 | */
58 | private String mSaveFilePath;
59 |
60 | private MediaProjection mMediaProjection;
61 | private MediaCodec mVideoEncoder;
62 | private Surface mSurface;
63 | private MediaMuxer mMuxer;
64 |
65 | private boolean mMuxerStarted = false;
66 | private int mVideoTrackIndex = -1;
67 |
68 | private AtomicBoolean mAtomicQuit = new AtomicBoolean(false);
69 |
70 | private MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
71 |
72 | private VirtualDisplay mVirtualDisplay;
73 |
74 |
75 | public MyShoter(MediaProjection mMediaProjection, String filePath) {
76 | this(360, 640, 1000000, 1, 5, mMediaProjection, filePath);
77 | }
78 |
79 | public MyShoter(int width, int height, int bitRate, int dpi, int fps,
80 | MediaProjection mediaProjection, String filePath) {
81 | this.mWidth = width;
82 | this.mHeight = height;
83 | this.mBitRate = bitRate;
84 | this.mDpi = dpi;
85 | this.mFrameRate = fps;
86 | this.mMediaProjection = mediaProjection;
87 | if(!filePath.endsWith(".mp4"))
88 | filePath += ".mp4";
89 | this.mSaveFilePath = filePath;
90 | }
91 |
92 |
93 | public void stopShot() {
94 | mAtomicQuit.set(true);
95 | }
96 |
97 | @Override
98 | public void run() {
99 |
100 | Log.e(TAG, "run: " + mWidth + " " + mHeight + " " + mBitRate + " " + mDpi + " " +
101 | mFrameRate);
102 |
103 | try {
104 |
105 | prepareEncoder();
106 | mMuxer = new MediaMuxer(mSaveFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
107 | Log.e(TAG, "run: mMuxer init");
108 |
109 | mVirtualDisplay =
110 | mMediaProjection.createVirtualDisplay(TAG + "_Video", mWidth, mHeight, mDpi,
111 | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC, mSurface, null, null);
112 | shotDisplay();
113 | } catch(IOException e) {
114 | e.printStackTrace();
115 | throw new RuntimeException("Muxur:::", e);
116 | } finally {
117 | releaseEncoder();
118 | }
119 | }
120 |
121 | private void prepareEncoder() throws IOException {
122 |
123 | MediaFormat format =
124 | MediaFormat.createVideoFormat(VIDEO_MIME_TYPE, mWidth, mHeight);
125 |
126 | format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
127 | MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
128 | format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
129 | format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
130 | format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
131 |
132 | mVideoEncoder = MediaCodec.createEncoderByType(VIDEO_MIME_TYPE);
133 | mVideoEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
134 |
135 | mSurface = mVideoEncoder.createInputSurface();
136 |
137 | mVideoEncoder.start();
138 | }
139 |
140 |
141 | private void shotDisplay() {
142 | while(!mAtomicQuit.get()) {
143 | int bufferIndex = mVideoEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_US);
144 |
145 | if(bufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
146 | resetOutputFormat();
147 | } else if(bufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
148 | SystemClock.sleep(10);
149 | } else if(bufferIndex >= 0) {
150 | if(!mMuxerStarted) {
151 | throw new IllegalStateException("MediaMuxer is not add the addTrack format ");
152 | }
153 |
154 | encodeToVideoTrack(bufferIndex);
155 |
156 | mVideoEncoder.releaseOutputBuffer(bufferIndex, false);
157 | }
158 | }
159 | }
160 |
161 | private void resetOutputFormat() {
162 |
163 | if(mMuxerStarted) {
164 | throw new IllegalStateException("format changed");
165 | }
166 | MediaFormat newFormat = mVideoEncoder.getOutputFormat();
167 |
168 | mVideoTrackIndex = mMuxer.addTrack(newFormat);
169 | mMuxer.start();
170 | mMuxerStarted = true;
171 | }
172 |
173 | private void encodeToVideoTrack(int bufferIndex) {
174 | ByteBuffer encodeData = mVideoEncoder.getOutputBuffer(bufferIndex);
175 |
176 | if((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
177 | mBufferInfo.size = 0;
178 | }
179 |
180 | if(mBufferInfo.size == 0) {
181 | encodeData = null;
182 | } else {
183 | //还不清楚到哪里去的.
184 | }
185 |
186 | if(encodeData != null) {
187 | encodeData.position(mBufferInfo.offset);
188 | encodeData.limit(mBufferInfo.offset + mBufferInfo.size);
189 |
190 | mMuxer.writeSampleData(mVideoTrackIndex, encodeData, mBufferInfo);
191 | }
192 |
193 |
194 | }
195 |
196 | private void releaseEncoder() {
197 | if(mVideoEncoder != null) {
198 | mVideoEncoder.stop();
199 | mVideoEncoder.release();
200 | mVideoEncoder = null;
201 | }
202 |
203 | if(mVirtualDisplay != null) {
204 | mVirtualDisplay.release();
205 | mVirtualDisplay = null;
206 | }
207 |
208 | if(mMediaProjection != null) {
209 | mMediaProjection.stop();
210 | mMediaProjection = null;
211 | }
212 |
213 | if(mMuxer != null) {
214 | mMuxer.stop();
215 | mMuxer.release();
216 | mMuxer = null;
217 | }
218 |
219 | mBufferInfo = null;
220 | mVideoTrackIndex = -1;
221 |
222 | }
223 |
224 |
225 | }
226 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/fileselector/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot.fileselector.utils;
2 |
3 |
4 | import com.gson8.myscreenshot.R;
5 | import com.gson8.myscreenshot.fileselector.config.FileConfig;
6 |
7 | import java.io.File;
8 | import java.util.ArrayList;
9 | import java.util.Collections;
10 | import java.util.HashMap;
11 |
12 | public class FileUtils {
13 | private static FileCompare fileCompare = new FileCompare();
14 |
15 | //获取文件列表
16 | public static ArrayList> getFileList(String path) {
17 | File file;
18 | file = new File(path);
19 |
20 | if(file.exists()) {
21 |
22 | if(file.isDirectory()) {
23 |
24 | File[] files = file.listFiles();
25 | ArrayList> ds = new ArrayList<>();
26 | ArrayList> fs = new ArrayList<>();
27 | if(!path.equals(FileConfig.rootPath)) {
28 | HashMap up = new HashMap<>(3);
29 | up.put(FileSelectorConfig.NAME, "...返回上一级");
30 | up.put(FileSelectorConfig.ICON, R.drawable.ic_back_file_selector);
31 | up.put(FileSelectorConfig.PATH, path);
32 | up.put(FileSelectorConfig.TYPE, FileType.UPTO);
33 | //up.put(FileConfig.SELECT, FileType.forbid);
34 | ds.add(up);
35 | }
36 |
37 | for(File e : files) {
38 | HashMap value = new HashMap<>(3);
39 | String p = e.getAbsolutePath(); //每个文件的路径
40 | String name = getFileName(p); //每个文件的名字
41 |
42 | /**
43 | * 隐藏文件处理
44 | */
45 | if(isHitFiles(name)) {
46 | if(!FileConfig.showHiddenFiles) {
47 | continue;
48 | }
49 | }
50 |
51 | /**
52 | * 文件夹处理
53 | */
54 | if(e.isDirectory()) {
55 | value.put(FileSelectorConfig.NAME, name);
56 | value.put(FileSelectorConfig.PATH, p);
57 | value.put(FileSelectorConfig.ICON, R.drawable.ic_back_file_selector);
58 | value.put(FileSelectorConfig.TYPE, FileType.FOLDER);
59 | //value.put(FileConfig.SELECT, FileConfig.selectType == FileType.FILE ? FileType.forbid : FileType.unselect);
60 | ds.add(value);
61 | } else //文件处理
62 | {
63 | String lastName = getFileLastName(name);
64 |
65 | //如果需要过滤
66 | if(FileConfig.filterModel != FileFilter.FILTER_NONE) {
67 | //如果是positive过滤
68 | if(FileConfig.positiveFiter) {
69 | //如果匹配不成功,则跳过此次循环
70 | if(!FileFilter.doFilter(lastName)) {
71 | continue;
72 | }
73 | } else {//native 过滤
74 | //如果匹配成功则跳过此次循环
75 | if(FileFilter.doFilter(lastName)) {
76 | continue;
77 | }
78 | }
79 | }
80 |
81 | int type = getFileType(name);
82 | int icon;
83 | switch(type) {
84 | case FileType.AUDIO:
85 | icon = R.drawable.ic_music_file_selector;
86 | break;
87 | case FileType.VIDEO:
88 | icon = R.drawable.ic_movie_file_selector;
89 | break;
90 | case FileType.TEX:
91 | icon = R.drawable.ic_txt_file_selector;
92 | break;
93 | case FileType.IMAGE:
94 | icon = R.drawable.ic_photo_file_selector;
95 | break;
96 | case FileType.COMPRESSION:
97 | icon = R.drawable.ic_compro_file_selector;
98 | break;
99 | default:
100 | icon = R.drawable.ic_other_file_selector;
101 | break;
102 | }
103 |
104 | value.put(FileSelectorConfig.NAME, name);
105 | value.put(FileSelectorConfig.PATH, p);
106 | value.put(FileSelectorConfig.ICON, icon);
107 | value.put(FileSelectorConfig.TYPE, FileType.FILE);
108 | //value.put(FileConfig.SELECT, FileConfig.selectType == FileType.FOLDER ? FileType.forbid : FileType.unselect);
109 |
110 | fs.add(value);
111 |
112 | }
113 | }
114 |
115 | Collections.sort(ds, fileCompare);
116 | Collections.sort(fs, fileCompare);
117 |
118 | ds.addAll(fs);
119 | return ds;
120 | }
121 | }
122 | return null;
123 |
124 | }
125 |
126 | //获取文件的种类
127 | public static int getFileType(String name) {
128 | int type = FileType.OTHER;
129 |
130 | String last = getFileLastName(name);
131 | if(last == null)
132 | return type;
133 |
134 | if(last.equals("jpg") | last.equals("png") | last.equals("bmp") | last.equals("gif")) {
135 | type = FileType.IMAGE;
136 | } else if(last.equals("avi") | last.equals("mp4") | last.equals("mkv") |
137 | last.equals("flv") | last.equals("rmvb")) {
138 | type = FileType.VIDEO;
139 | } else if(last.equals("txt") | last.equals("c") | last.equals("cpp") | last.equals("java") |
140 | last.equals("xml"))
141 |
142 | {
143 | type = FileType.TEX;
144 | } else if(last.equals("mp3") | last.equals("m4a") | last.equals("ogg") |
145 | last.equals("flac") | last.equals("ape") | last.equals("aac")) {
146 | type = FileType.AUDIO;
147 | } else if(last.equals("zip") || last.equals("rar")) {
148 | type = FileType.COMPRESSION;
149 | }
150 | return type;
151 | }
152 |
153 | //获取文件的后缀名
154 | public static String getFileLastName(String name) {
155 | if(!name.contains(".")) {
156 | return null;
157 | }
158 | return name.substring(name.lastIndexOf(".") + 1);
159 | }
160 |
161 | //通过文件路径获取文件的名字
162 |
163 | public static String getFileName(String path) {
164 | return path.substring(path.lastIndexOf('/') + 1, path.length());
165 | }
166 |
167 | //判断文件是否是隐藏文件
168 | public static boolean isHitFiles(String name) {
169 | return name.substring(0, 1).equals(".");
170 | }
171 |
172 | //获取文件父目录
173 | public static String getParentPath(String path) {
174 | File file = new File(path);
175 |
176 | if(file.exists()) {
177 | return file.getParent();
178 | }
179 |
180 | return null;
181 | }
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/app/src/main/java/com/gson8/myscreenshot/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.gson8.myscreenshot;
2 |
3 | import android.Manifest;
4 | import android.annotation.TargetApi;
5 | import android.content.Intent;
6 | import android.content.pm.PackageManager;
7 | import android.media.projection.MediaProjection;
8 | import android.media.projection.MediaProjectionManager;
9 | import android.net.Uri;
10 | import android.os.Build;
11 | import android.os.Bundle;
12 | import android.os.Environment;
13 | import android.provider.Settings;
14 | import android.support.annotation.NonNull;
15 | import android.support.v4.app.ActivityCompat;
16 | import android.support.v4.content.ContextCompat;
17 | import android.support.v7.app.AppCompatActivity;
18 | import android.util.DisplayMetrics;
19 | import android.util.Log;
20 | import android.view.View;
21 | import android.widget.AdapterView;
22 | import android.widget.Button;
23 | import android.widget.CompoundButton;
24 | import android.widget.Spinner;
25 | import android.widget.Switch;
26 | import android.widget.Toast;
27 |
28 | import com.gson8.myscreenshot.fileselector.config.FileConfig;
29 | import com.gson8.myscreenshot.fileselector.dialog.FileDialog;
30 | import com.gson8.myscreenshot.video.DpiBean;
31 | import com.gson8.myscreenshot.video.MyShoter;
32 | import com.gson8.myscreenshot.video.SpinnerAdapter;
33 |
34 | import java.io.File;
35 | import java.util.ArrayList;
36 | import java.util.List;
37 |
38 | public class MainActivity extends AppCompatActivity implements View.OnClickListener,
39 | CompoundButton.OnCheckedChangeListener, AdapterView.OnItemSelectedListener {
40 |
41 | public static final int REQUEST_CODE = 0x123;
42 | public static final int REQUEST_SDCARD_CODE = 0x1243;
43 | public static final int REQUEST_SETTING_CODE = 0x1223;
44 | private static final String TAG = "TAGGG";
45 |
46 |
47 | private Button mBtnShotStart;
48 | private Button mBtnOp;
49 |
50 | private Spinner mDpiSizeSp;
51 | private SpinnerAdapter mDpiAdapter;
52 |
53 | private Spinner mBitRateSp;
54 | private SpinnerAdapter mBitRateAdapter;
55 |
56 | private Spinner mFpsSp;
57 | private SpinnerAdapter mFpsAdapter;
58 |
59 | private Switch mShowTouchSwitch;
60 |
61 |
62 | //初始化分辨率
63 | private DpiBean mDpiSizeBean;
64 | private List mSizes;
65 |
66 |
67 | //初始化bitRate
68 | private int mBitRate = 600000; //6 Mbps
69 | private Integer[] BIT_RATE_DATA =
70 | {500000, 1000000, 2000000, 2500000, 3000000, 4000000, 5000000, 6000000, 8000000,
71 | 10000000, 12000000};
72 |
73 | //初始化FPS
74 | private int mFps = 5;
75 | private Integer[] FPS_DATA = {5, 6, 8, 10, 12, 15, 18, 20, 24, 30};
76 |
77 | private MediaProjectionManager mMediaProjectionManager;
78 | private MediaProjection mMediaProjection;
79 |
80 | private MyShoter mShoter;
81 |
82 |
83 | private File mFile;
84 |
85 |
86 | @Override
87 | protected void onCreate(Bundle savedInstanceState) {
88 | super.onCreate(savedInstanceState);
89 | setContentView(R.layout.activity_main);
90 |
91 |
92 | initView();
93 |
94 |
95 | initDPIData();
96 |
97 | initEvent();
98 |
99 | mMediaProjectionManager =
100 | (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
101 |
102 | checkSDCardPermission();
103 | }
104 |
105 |
106 | private void initView() {
107 |
108 | mBtnShotStart = (Button) findViewById(R.id.id_shot_video);
109 | mBtnOp = (Button) findViewById(R.id.id_video_op);
110 | mDpiSizeSp = (Spinner) findViewById(R.id.id_sp_select_dpi);
111 | mBitRateSp = (Spinner) findViewById(R.id.id_sp_select_mbps);
112 | mFpsSp = (Spinner) findViewById(R.id.id_sp_select_fps);
113 | mShowTouchSwitch = (Switch) findViewById(R.id.id_show_touch);
114 |
115 |
116 | }
117 |
118 | private void initDPIData() {
119 | mSizes = new ArrayList<>();
120 | DisplayMetrics metrics = getResources().getDisplayMetrics();
121 | mDpiSizeBean = new DpiBean(metrics.widthPixels, metrics.heightPixels);
122 | if(mSizes.size() == 0) {
123 | int h = mDpiSizeBean.getHeight();
124 | if(h > 1920)
125 | mSizes.add(mDpiSizeBean);
126 | if(h == 1920)
127 | mSizes.add(new DpiBean(1080, 1920));
128 | if(h >= 1280)
129 | mSizes.add(new DpiBean(720, 1280));
130 | if(h >= 960)
131 | mSizes.add(new DpiBean(540, 960));
132 | if(h >= 854)
133 | mSizes.add(new DpiBean(480, 854));
134 | if(h >= 640)
135 | mSizes.add(new DpiBean(360, 640));
136 | if(h >= 426)
137 | mSizes.add(new DpiBean(240, 426));
138 | }
139 | }
140 |
141 | private void initEvent() {
142 | mBtnShotStart.setOnClickListener(this);
143 | mBtnOp.setOnClickListener(this);
144 | mShowTouchSwitch.setOnCheckedChangeListener(this);
145 |
146 |
147 | mDpiAdapter = new SpinnerAdapter(this, mSizes.toArray());
148 | mDpiSizeSp.setAdapter(mDpiAdapter);
149 |
150 | mBitRateAdapter = new SpinnerAdapter(this, BIT_RATE_DATA);
151 | mBitRateSp.setAdapter(mBitRateAdapter);
152 |
153 | mFpsAdapter = new SpinnerAdapter(this, FPS_DATA);
154 | mFpsSp.setAdapter(mFpsAdapter);
155 |
156 |
157 | mDpiSizeSp.setOnItemSelectedListener(this);
158 | mBitRateSp.setOnItemSelectedListener(this);
159 | mFpsSp.setOnItemSelectedListener(this);
160 | }
161 |
162 | @TargetApi(Build.VERSION_CODES.M)
163 | private void checkSDCardPermission() {
164 | if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
165 | PackageManager.PERMISSION_GRANTED) {
166 | //没有权限,去申请权限
167 | ActivityCompat.requestPermissions(this,
168 | new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_SDCARD_CODE);
169 |
170 | }
171 | }
172 |
173 | private void checkTwoSettings() {
174 | boolean retVal = Settings.System.canWrite(this);
175 | if(!retVal) {
176 | Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
177 | intent.setData(Uri.parse("package:" + getPackageName()));
178 | startActivity(intent);
179 | }
180 | }
181 |
182 | /**
183 | * 显示触摸操作
184 | *
185 | * @param b
186 | */
187 | public void showTouchDot(boolean b) {
188 | if(b) {
189 | Settings.System.putInt(getContentResolver(),
190 | "show_touches", 1);
191 | } else {
192 | Settings.System.putInt(getContentResolver(),
193 | "show_touches", 0);
194 | }
195 | }
196 |
197 | @TargetApi(Build.VERSION_CODES.M)
198 | @Override
199 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
200 | @NonNull int[] grantResults) {
201 | if(requestCode == REQUEST_SDCARD_CODE) {
202 | if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
203 | } else {
204 | Toast.makeText(this, "没有写入内存卡的权限", Toast.LENGTH_SHORT).show();
205 | }
206 | } else if(requestCode == REQUEST_SETTING_CODE) {
207 | if(grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
208 | } else {
209 | checkTwoSettings();
210 | }
211 | }
212 | }
213 |
214 | @Override
215 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
216 | switch(buttonView.getId()) {
217 | case R.id.id_show_touch:
218 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
219 | if(!Settings.System.canWrite(this)) {
220 | mShowTouchSwitch.setChecked(false);
221 | Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
222 | Uri.parse("package:" + getPackageName()));
223 | startActivityForResult(intent, REQUEST_SETTING_CODE);
224 | } else {
225 | showTouchDot(isChecked);
226 | }
227 | } else {
228 | // < 6.0
229 | showTouchDot(isChecked);
230 | }
231 | break;
232 | }
233 | }
234 |
235 |
236 | private void shot() {
237 | if(mShoter != null) {
238 | mShoter.stopShot();
239 | mShoter = null;
240 | mBtnShotStart.setText("开始录制屏幕");
241 | } else {
242 | Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
243 | startActivityForResult(captureIntent, REQUEST_CODE);
244 | }
245 | }
246 |
247 | @Override
248 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
249 | if(requestCode == REQUEST_CODE) {
250 | startShotNow(resultCode, data);
251 | }
252 | if(requestCode == REQUEST_SETTING_CODE) {
253 | if(Settings.System.canWrite(this)) {
254 | //检查返回结果
255 | Toast.makeText(this, "OK",
256 | Toast.LENGTH_SHORT).show();
257 | } else {
258 | Toast.makeText(this, "没有修改系统设置的权限",
259 | Toast.LENGTH_SHORT).show();
260 | }
261 | }
262 | }
263 |
264 | public void startShotNow(int resultCode, Intent data) {
265 | mMediaProjection =
266 | mMediaProjectionManager.getMediaProjection(resultCode, data);
267 |
268 | if(mMediaProjection == null) {
269 | Log.e(TAG, "MediaProjection is null");
270 | return;
271 | }
272 |
273 | mFile = new File(getRandomFileName());
274 |
275 | Log.e(TAG, "startShotNow: " + mDpiSizeBean.getHeight() + " " + mBitRate + " " + mFps);
276 |
277 |
278 | mShoter = new MyShoter(mDpiSizeBean.getWidth(), mDpiSizeBean.getHeight(), mBitRate, 1,
279 | mFps, mMediaProjection, mFile.getAbsolutePath());
280 |
281 | new Thread(mShoter).start();
282 | mBtnShotStart.setText("停止录制");
283 |
284 | moveTaskToBack(true);
285 | }
286 |
287 | @Override
288 | protected void onDestroy() {
289 | super.onDestroy();
290 | if(mShoter != null) {
291 | mShoter.stopShot();
292 | mShoter = null;
293 | }
294 | }
295 |
296 | @Override
297 | public void onClick(View v) {
298 | switch(v.getId()) {
299 | case R.id.id_shot_video:
300 | shot();
301 | break;
302 | case R.id.id_video_op:
303 | opTheVideo();
304 | break;
305 | }
306 | }
307 |
308 | private void opTheVideo() {
309 |
310 | FileConfig config = new FileConfig();
311 |
312 | FileDialog fileDialog = new FileDialog(this, config);
313 | fileDialog.showDialog();
314 | }
315 |
316 |
317 | @Override
318 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
319 | switch(parent.getId()) {
320 | case R.id.id_sp_select_dpi:
321 | mDpiSizeBean = mSizes.get(position);
322 | break;
323 | case R.id.id_sp_select_mbps:
324 | mBitRate = BIT_RATE_DATA[position];
325 | break;
326 | case R.id.id_sp_select_fps:
327 | mFps = FPS_DATA[position];
328 | break;
329 | }
330 | }
331 |
332 | @Override
333 | public void onNothingSelected(AdapterView> parent) {
334 |
335 | }
336 |
337 | /**
338 | * 返回一个文件名
339 | *
340 | * @return
341 | */
342 | public String getRandomFileName() {
343 | return Environment.getExternalStorageDirectory() + "/Video_" +
344 | ((int) (System.currentTimeMillis() / 1000)) + ".mp4";
345 | }
346 | }
347 |
--------------------------------------------------------------------------------