├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── release │ ├── app-release.apk │ └── output.json └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── weibu │ │ └── recoderboard │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── weibu │ │ │ └── recoderboard │ │ │ ├── BaseActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── SplashActivity.java │ │ │ ├── entity │ │ │ ├── CarNumberMsg.java │ │ │ ├── LocationMsg.java │ │ │ └── RecoderMsg.java │ │ │ ├── fragment │ │ │ └── SettingPrefsFragment.java │ │ │ ├── logic │ │ │ ├── GdLocationManager.java │ │ │ └── RecordRepeatManager.java │ │ │ ├── util │ │ │ ├── CameraUtils.java │ │ │ ├── Constant.java │ │ │ ├── MediaUtils.java │ │ │ └── Utils.java │ │ │ ├── viewmanager │ │ │ ├── IViewManager.java │ │ │ ├── MarkViewManager.java │ │ │ ├── RecoderViewManager.java │ │ │ └── SettingViewManager.java │ │ │ └── widget │ │ │ └── AlwaysMarqueeTextView.java │ ├── jniLibs │ │ ├── arm64-v8a │ │ │ ├── libGNaviData.so │ │ │ ├── libGNaviMap.so │ │ │ ├── libGNaviMapex.so │ │ │ ├── libGNaviSearch.so │ │ │ ├── libGNaviUtils.so │ │ │ └── libRoadLineRebuildAPI.so │ │ ├── armeabi-v7a │ │ │ ├── libGNaviData.so │ │ │ ├── libGNaviMap.so │ │ │ ├── libGNaviMapex.so │ │ │ ├── libGNaviSearch.so │ │ │ ├── libGNaviUtils.so │ │ │ └── libRoadLineRebuildAPI.so │ │ ├── armeabi │ │ │ ├── libGNaviData.so │ │ │ ├── libGNaviMap.so │ │ │ ├── libGNaviMapex.so │ │ │ ├── libGNaviSearch.so │ │ │ ├── libGNaviUtils.so │ │ │ └── libRoadLineRebuildAPI.so │ │ ├── x86 │ │ │ ├── libGNaviData.so │ │ │ ├── libGNaviMap.so │ │ │ ├── libGNaviMapex.so │ │ │ ├── libGNaviSearch.so │ │ │ ├── libGNaviUtils.so │ │ │ └── libRoadLineRebuildAPI.so │ │ └── x86_64 │ │ │ ├── libGNaviData.so │ │ │ ├── libGNaviMap.so │ │ │ ├── libGNaviMapex.so │ │ │ ├── libGNaviSearch.so │ │ │ ├── libGNaviUtils.so │ │ │ └── libRoadLineRebuildAPI.so │ └── res │ │ ├── animator │ │ ├── slide_in_left.xml │ │ └── slide_out_right.xml │ │ ├── drawable-hdpi │ │ ├── icon_setting.png │ │ ├── record.png │ │ ├── recording.png │ │ ├── recordpressed.png │ │ ├── stop.png │ │ └── stoppressed.png │ │ ├── drawable │ │ ├── recoder.xml │ │ └── recoder_stop.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── lay_mark.xml │ │ ├── lay_recoder.xml │ │ └── lay_setting.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── array.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── setting_preferences.xml │ └── test │ └── java │ └── com │ └── weibu │ └── recoderboard │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 行车记录仪 2 | 1. 介绍 3 | 2. 作者 4 | 3. 截图 5 | 4. 版本 6 | 7 | 8 | > 记录你的生活 9 | 10 | **介绍** 11 | 12 | 这是一款行车记录仪 -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | signingConfigs { 5 | config { 6 | keyAlias 'key0' 7 | keyPassword '123456' 8 | storeFile file('C:/Users/user/Desktop/keystore.jks') 9 | storePassword '123456' 10 | } 11 | } 12 | compileSdkVersion 25 13 | buildToolsVersion "26.0.0" 14 | defaultConfig { 15 | applicationId "com.weibu.recoderboard" 16 | minSdkVersion 19 17 | targetSdkVersion 25 18 | versionCode 1 19 | versionName "1.0" 20 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 21 | } 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | } 29 | 30 | dependencies { 31 | compile fileTree(include: ['*.jar'], dir: 'libs') 32 | compile 'com.android.support:appcompat-v7:25.0.1' 33 | testCompile 'junit:junit:4.12' 34 | compile 'com.werb.permissionschecker:permissionschecker:0.0.1-beta2' 35 | compile 'org.greenrobot:eventbus:3.0.0' 36 | 37 | //高德地图 38 | compile 'com.amap.api:3dmap:latest.integration'//3D地图 39 | compile 'com.amap.api:location:latest.integration'//定位 40 | // compile 'com.amap.api:navi-3dmap:latest.integration'//导航 41 | } 42 | -------------------------------------------------------------------------------- /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:\DevTools\adt-bundle-windows-x86_64-20140702\sdk/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -keepattributes *Annotation* 27 | -keepclassmembers class ** { 28 | @org.greenrobot.eventbus.Subscribe ; 29 | } 30 | -keep enum org.greenrobot.eventbus.ThreadMode { *; } 31 | 32 | 33 | 34 | #3D 地图 V5.0.0之后: 35 | -keep class com.amap.api.maps.**{*;} 36 | -keep class com.autonavi.**{*;} 37 | -keep class com.amap.api.trace.**{*;} 38 | 39 | #定位 40 | -keep class com.amap.api.location.**{*;} 41 | -keep class com.amap.api.fence.**{*;} 42 | -keep class com.autonavi.aps.amapapi.model.**{*;} 43 | 44 | #2D地图 45 | -keep class com.amap.api.maps2d.**{*;} 46 | -keep class com.amap.api.mapcore2d.**{*;} 47 | 48 | #导航 49 | -keep class com.amap.api.navi.**{*;} 50 | -keep class com.autonavi.**{*;} 51 | -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/release/app-release.apk -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1},"outputFile":{"path":"C:\\Users\\user\\Desktop\\carboard\\RecoderBoard\\app\\release\\app-release.apk"},"properties":{"packageId":"com.weibu.recoderboard","split":""}}] -------------------------------------------------------------------------------- /app/src/androidTest/java/com/weibu/recoderboard/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | //package com.weibu.recoderboard; 2 | // 3 | //import android.content.Context; 4 | //import android.support.test.InstrumentationRegistry; 5 | //import android.support.test.runner.AndroidJUnit4; 6 | // 7 | //import org.junit.Test; 8 | //import org.junit.runner.RunWith; 9 | // 10 | //import static org.junit.Assert.*; 11 | // 12 | ///** 13 | // * Instrumented test, which will execute on an Android device. 14 | // * 15 | // * @see Testing documentation 16 | // */ 17 | //@RunWith(AndroidJUnit4.class) 18 | //public class ExampleInstrumentedTest { 19 | // @Test 20 | // public void useAppContext() throws Exception { 21 | // // Context of the app under test. 22 | // Context appContext = InstrumentationRegistry.getTargetContext(); 23 | // 24 | // assertEquals("com.weibu.recoderboard", appContext.getPackageName()); 25 | // } 26 | //} 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 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 | 52 | 53 | 54 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.view.View; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | 10 | /** 11 | * Created by blueberry on 2017/7/13. 12 | * Activity基类 13 | */ 14 | 15 | public abstract class BaseActivity extends Activity { 16 | 17 | protected abstract int getContentLayout(); 18 | protected abstract void initView(); 19 | protected abstract void initData(); 20 | 21 | @Override 22 | protected void onCreate(@Nullable Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | requestWindowFeature(Window.FEATURE_NO_TITLE); 25 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏 26 | if(getContentLayout() != 0) { 27 | setContentView(getContentLayout()); 28 | } 29 | initView(); 30 | initData(); 31 | } 32 | 33 | @Override 34 | public void onWindowFocusChanged(boolean hasFocus) { 35 | super.onWindowFocusChanged(hasFocus); 36 | if(hasFocus){ 37 | hideNavigationBar();//隐藏导航栏 38 | } 39 | } 40 | 41 | public void hideNavigationBar() { 42 | int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE 43 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 44 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 45 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar 46 | | View.SYSTEM_UI_FLAG_FULLSCREEN; // hide status bar 47 | if( android.os.Build.VERSION.SDK_INT >= 19 ){ 48 | uiFlags |= 0x00001000; //SYSTEM_UI_FLAG_IMMERSIVE_STICKY: hide navigation bars - compatibility: building API level is lower thatn 19, use magic number directly for higher API target level 49 | } else { 50 | uiFlags |= View.SYSTEM_UI_FLAG_LOW_PROFILE; 51 | } 52 | getWindow().getDecorView().setSystemUiVisibility(uiFlags); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard; 2 | 3 | import android.content.SharedPreferences; 4 | import android.os.Environment; 5 | import android.preference.PreferenceManager; 6 | import android.text.TextUtils; 7 | import android.util.Log; 8 | import android.view.KeyEvent; 9 | import android.view.MotionEvent; 10 | import android.view.SurfaceView; 11 | import com.weibu.recoderboard.fragment.SettingPrefsFragment; 12 | import com.weibu.recoderboard.logic.GdLocationManager; 13 | import com.weibu.recoderboard.logic.RecordRepeatManager; 14 | import com.weibu.recoderboard.util.Constant; 15 | import com.weibu.recoderboard.util.MediaUtils; 16 | import com.weibu.recoderboard.viewmanager.MarkViewManager; 17 | import com.weibu.recoderboard.viewmanager.RecoderViewManager; 18 | import com.weibu.recoderboard.viewmanager.SettingViewManager; 19 | import java.util.UUID; 20 | 21 | /** 22 | * Created by blueberry on 2017/7/13. 23 | * 主界面 24 | */ 25 | 26 | public class MainActivity extends BaseActivity{ 27 | 28 | private SurfaceView surfaceView; 29 | private MediaUtils mediaUtils; 30 | private SettingPrefsFragment settingPrefsFragment; 31 | // private RecoderViewManager recoderViewManager; 32 | private SettingViewManager settingViewManager; 33 | private MarkViewManager markViewManager; 34 | private static long delayHide = 5*1000; 35 | private static long defaultRecoderDurion = 25*1000; 36 | 37 | 38 | @Override 39 | protected int getContentLayout() { 40 | return R.layout.activity_main; 41 | } 42 | 43 | @Override 44 | protected void initView() { 45 | surfaceView = (SurfaceView) findViewById(R.id.sf_preview); 46 | settingPrefsFragment = SettingPrefsFragment.newInstance(); 47 | // recoderViewManager = new RecoderViewManager(this).initView(); 48 | settingViewManager = new SettingViewManager(this).initView(); 49 | markViewManager = new MarkViewManager(this).initView(); 50 | } 51 | 52 | @Override 53 | protected void initData() { 54 | //mediaUtils = new MediaUtils(this); 55 | mediaUtils = MediaUtils.getInstance(this); 56 | mediaUtils.setRecorderType(MediaUtils.MEDIA_VIDEO); 57 | mediaUtils.setTargetDir(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)); 58 | mediaUtils.setTargetName(UUID.randomUUID() + ".mp4"); 59 | mediaUtils.setSurfaceView(surfaceView);//设置surfaceView 60 | 61 | long durion = getReateRecoderDurion(); 62 | Log.i("xxx","durion:"+durion); 63 | RecordRepeatManager.getInstance(this).setRecordDurion(durion).setRecordInterval(500).startRecordAuto();//开始循环录制 64 | // recoderViewManager.initData().hideDelay(delay);//delay秒无操作消失 65 | settingViewManager.initData().hideDelay(delayHide); 66 | markViewManager.initData();//水印部分(车牌号,位置,时间。。。) 67 | 68 | GdLocationManager.getInstance(this).startLocation(); 69 | 70 | } 71 | 72 | private long getReateRecoderDurion() { 73 | SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(this); 74 | String recoder_time = shp.getString(Constant.prefs_key_recoder_time, ""); 75 | if (TextUtils.isEmpty(recoder_time)) { 76 | return defaultRecoderDurion; 77 | } else { 78 | int i = Integer.parseInt(recoder_time); 79 | switch (i) { 80 | case 0: 81 | return 1*60*1000;//1分钟 82 | case 1: 83 | return 3*60*1000;//3分钟 84 | case 2: 85 | return 5*60*1000;//5分钟 86 | 87 | } 88 | return defaultRecoderDurion; 89 | } 90 | 91 | 92 | } 93 | 94 | public void record() { 95 | mediaUtils.record(); 96 | } 97 | 98 | public void stopRecordSave() { 99 | mediaUtils.stopRecordSave(); 100 | } 101 | 102 | public boolean isRecording() { 103 | return mediaUtils.isRecording(); 104 | } 105 | 106 | /** 107 | * 显示设置界面 108 | */ 109 | public void showSettingLay(){ 110 | 111 | if(!settingPrefsFragment.isVisible()) { 112 | 113 | // recoderViewManager.hide(); 114 | settingViewManager.hide(); 115 | 116 | if (!settingPrefsFragment.isAdded()) { 117 | getFragmentManager().beginTransaction() 118 | .setCustomAnimations(R.animator.slide_in_left,R.animator.slide_out_right) 119 | .add(R.id.setting_content, settingPrefsFragment) 120 | .addToBackStack(null) 121 | .commit(); 122 | }else{ 123 | getFragmentManager().beginTransaction() 124 | .setCustomAnimations(R.animator.slide_in_left,R.animator.slide_out_right) 125 | .show(settingPrefsFragment) 126 | .addToBackStack(null) 127 | .commit(); 128 | } 129 | } 130 | } 131 | 132 | /** 133 | * 隐藏设置界面 134 | */ 135 | public void hideSettingLay(){ 136 | 137 | if(settingPrefsFragment != null && settingPrefsFragment.isVisible()){ 138 | 139 | // recoderViewManager.showContinue(); 140 | settingViewManager.showContinue(); 141 | 142 | getFragmentManager().beginTransaction() 143 | .setCustomAnimations(R.animator.slide_in_left,R.animator.slide_out_right) 144 | .hide(settingPrefsFragment) 145 | .commit(); 146 | } 147 | } 148 | @Override 149 | protected void onStop() { 150 | super.onStop(); 151 | // recoderViewManager.stop(); 152 | settingViewManager.stop(); 153 | GdLocationManager.getInstance(this).stopLocation(); 154 | } 155 | 156 | @Override 157 | protected void onDestroy() { 158 | super.onDestroy(); 159 | GdLocationManager.getInstance(this).destroyLocation(); 160 | } 161 | 162 | @Override 163 | public boolean onKeyDown(int keyCode, KeyEvent event) { 164 | settingViewManager.showContinue(); 165 | return super.onKeyDown(keyCode, event); 166 | } 167 | 168 | @Override 169 | public boolean onTouchEvent(MotionEvent event) { 170 | 171 | if (event.getAction() == MotionEvent.ACTION_DOWN) { 172 | hideSettingLay();//触摸预览界面隐藏设置界面 173 | settingViewManager.showContinue();//界面有操作再延长delay秒消失 174 | // recoderViewManager.showContinue(); 175 | 176 | } else if (event.getAction() == MotionEvent.ACTION_UP) { 177 | 178 | } else if (event.getAction() == MotionEvent.ACTION_MOVE) { 179 | } 180 | return false; 181 | 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | import android.support.annotation.NonNull; 7 | import java.util.List; 8 | import com.werb.permissionschecker.PermissionChecker; 9 | 10 | /** 11 | * Created by blueberry on 2017/7/13. 12 | * 预留闪屏页,为了在6.0以上机子上测试,相机,录像权限兼容等 13 | */ 14 | 15 | public class SplashActivity extends BaseActivity { 16 | 17 | static final String[] PERMISSIONS = new String[]{ 18 | Manifest.permission.RECORD_AUDIO, 19 | Manifest.permission.CAMERA, 20 | Manifest.permission.READ_EXTERNAL_STORAGE, 21 | Manifest.permission.ACCESS_COARSE_LOCATION, 22 | Manifest.permission.ACCESS_FINE_LOCATION, 23 | }; 24 | private PermissionChecker permissionChecker; 25 | 26 | @Override 27 | protected int getContentLayout() { 28 | return 0; 29 | } 30 | 31 | @Override 32 | protected void initView() { 33 | 34 | } 35 | 36 | @Override 37 | protected void initData() { 38 | permissionChecker = new PermissionChecker(this); // initialize,must need 39 | if (permissionChecker.isLackPermissions(PERMISSIONS)) { 40 | permissionChecker.requestPermissions(); 41 | } else { 42 | startActivity(new Intent(this,MainActivity.class)); 43 | finish(); 44 | } 45 | } 46 | 47 | @Override 48 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 49 | switch (requestCode) { 50 | case PermissionChecker.PERMISSION_REQUEST_CODE: 51 | if (permissionChecker.hasAllPermissionsGranted(grantResults)) { 52 | startActivity(new Intent(this,MainActivity.class)); 53 | finish(); 54 | } else { 55 | permissionChecker.showDialog(); 56 | } 57 | break; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/entity/CarNumberMsg.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.entity; 2 | 3 | /** 4 | * Created by blueberry on 2017/7/14. 5 | */ 6 | 7 | public class CarNumberMsg { 8 | private String car_no; 9 | 10 | public CarNumberMsg(String car_no){ 11 | this.car_no = car_no; 12 | } 13 | public String getMessage() { 14 | return car_no; 15 | } 16 | 17 | public void setMessage(String car_no) { 18 | this.car_no = car_no; 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/entity/LocationMsg.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.entity; 2 | 3 | /** 4 | * Created by user on 2017/7/17. 5 | */ 6 | 7 | public class LocationMsg { 8 | private String msg_location; 9 | private float msg_speed; 10 | 11 | public String getMsg_location() { 12 | return msg_location; 13 | } 14 | 15 | public float getMsg_speed() { 16 | return msg_speed; 17 | } 18 | 19 | public void setMsg_location(String msg_location) { 20 | this.msg_location = msg_location; 21 | } 22 | 23 | public void setMsg_speed(float msg_speed) { 24 | this.msg_speed = msg_speed; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "LocationMsg{" + 30 | "msg_location='" + msg_location + '\'' + 31 | ", msg_speed='" + msg_speed + '\'' + 32 | '}'; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/entity/RecoderMsg.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.entity; 2 | 3 | /** 4 | * Created by user on 2017/7/18. 5 | */ 6 | 7 | public class RecoderMsg { 8 | 9 | private String Msg_durion; 10 | public RecoderMsg(String Msg_durion) { 11 | this.Msg_durion = Msg_durion; 12 | } 13 | 14 | public String getMsg_durion() { 15 | return Msg_durion; 16 | } 17 | 18 | public void setMsg_durion(String msg_durion) { 19 | Msg_durion = msg_durion; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return "RecoderMsg{" + 25 | "Msg_durion='" + Msg_durion + '\'' + 26 | '}'; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/fragment/SettingPrefsFragment.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.fragment; 2 | 3 | import android.content.SharedPreferences; 4 | import android.os.Bundle; 5 | import android.preference.EditTextPreference; 6 | import android.preference.ListPreference; 7 | import android.preference.Preference; 8 | import android.preference.PreferenceFragment; 9 | import android.preference.PreferenceManager; 10 | import android.preference.PreferenceScreen; 11 | import android.support.annotation.Nullable; 12 | import android.text.TextUtils; 13 | import android.util.Log; 14 | import android.view.LayoutInflater; 15 | import android.view.View; 16 | import android.view.ViewGroup; 17 | import com.weibu.recoderboard.R; 18 | import com.weibu.recoderboard.entity.CarNumberMsg; 19 | import com.weibu.recoderboard.entity.RecoderMsg; 20 | import com.weibu.recoderboard.util.Constant; 21 | import org.greenrobot.eventbus.EventBus; 22 | 23 | /** 24 | * Created by blueberry on 2017/7/14. 25 | * 设置主界面 26 | */ 27 | 28 | public class SettingPrefsFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener{ 29 | 30 | private ListPreference listPreference; 31 | private EditTextPreference editTextPreference; 32 | 33 | //获取实例 34 | public static SettingPrefsFragment newInstance() 35 | { 36 | SettingPrefsFragment settingPrefsFragment = new SettingPrefsFragment(); 37 | return settingPrefsFragment; 38 | } 39 | 40 | @Override 41 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 42 | View view = super.onCreateView(inflater, container, savedInstanceState); 43 | view.setBackgroundResource(android.R.color.white);//设置背景色为白色,否则默认透明 44 | // view.setAlpha(0.5f); 45 | 46 | editTextPreference = (EditTextPreference)findPreference(Constant.prefs_key_car_number); 47 | listPreference = (ListPreference)findPreference(Constant.prefs_key_recoder_time); 48 | editTextPreference.setOnPreferenceChangeListener(this); 49 | listPreference.setOnPreferenceChangeListener(this); 50 | 51 | initPreferencesValue();//初始化设置界面参数数据 52 | return view; 53 | } 54 | 55 | @Override 56 | public void onCreate(Bundle savedInstanceState) { 57 | // TODO Auto-generated method stub 58 | super.onCreate(savedInstanceState); 59 | addPreferencesFromResource(R.xml.setting_preferences); 60 | } 61 | private void initPreferencesValue(){ 62 | SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(getActivity()); 63 | String car_number = shp.getString(Constant.prefs_key_car_number,""); 64 | String recoder_time = shp.getString(Constant.prefs_key_recoder_time,""); 65 | if (!TextUtils.isEmpty(car_number)) { 66 | editTextPreference.setSummary(car_number); 67 | } 68 | 69 | if(!TextUtils.isEmpty(recoder_time)) { 70 | int i = Integer.parseInt(recoder_time); 71 | String[] array = getActivity().getResources().getStringArray(R.array.recoder_time); 72 | listPreference.setSummary(array[i]); 73 | listPreference.setValue(recoder_time); 74 | } 75 | 76 | 77 | } 78 | @Override 79 | public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 80 | return super.onPreferenceTreeClick(preferenceScreen, preference); 81 | } 82 | 83 | @Override 84 | public boolean onPreferenceChange(Preference preference, Object newValue) { 85 | 86 | if(newValue != null){ 87 | 88 | if(Constant.prefs_key_car_number.equals(preference.getKey())){ 89 | String value = newValue.toString(); 90 | if(!TextUtils.isEmpty(value)) { 91 | editTextPreference.setSummary(value); 92 | EventBus.getDefault().post(new CarNumberMsg(value));//EventBus发送car_no,MakrkViewManager类负责接收 93 | return true; 94 | } 95 | 96 | }else if(Constant.prefs_key_recoder_time.equals(preference.getKey())){ 97 | if(!TextUtils.isEmpty(newValue.toString())) { 98 | int i = Integer.parseInt(newValue.toString()); 99 | String[] array = getActivity().getResources().getStringArray(R.array.recoder_time); 100 | listPreference.setSummary(array[i]); 101 | EventBus.getDefault().post(new RecoderMsg(newValue.toString())); 102 | return true; 103 | } 104 | } 105 | } 106 | return false; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/logic/GdLocationManager.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.logic; 2 | 3 | import android.app.Activity; 4 | import android.util.Log; 5 | 6 | import com.amap.api.location.AMapLocation; 7 | import com.amap.api.location.AMapLocationClient; 8 | import com.amap.api.location.AMapLocationClientOption; 9 | import com.amap.api.location.AMapLocationListener; 10 | import com.weibu.recoderboard.entity.CarNumberMsg; 11 | import com.weibu.recoderboard.entity.LocationMsg; 12 | 13 | import org.greenrobot.eventbus.EventBus; 14 | 15 | 16 | /** 17 | * Created by blueberry on 2017/7/17. 18 | * 高德地图,获取位置,速度 19 | */ 20 | 21 | public class GdLocationManager { 22 | private static GdLocationManager mInstance = null; 23 | private Activity context; 24 | private AMapLocationClient locationClient = null; 25 | private AMapLocationClientOption locationOption = null; 26 | private LocationMsg msg; 27 | 28 | public static GdLocationManager getInstance(Activity context) { 29 | if (mInstance == null) { 30 | synchronized (GdLocationManager.class) { 31 | if (mInstance == null) { 32 | mInstance = new GdLocationManager(context); 33 | } 34 | } 35 | } 36 | return mInstance; 37 | } 38 | private GdLocationManager(Activity activity) { 39 | this.context = activity; 40 | initLocation(); 41 | } 42 | 43 | private void initLocation() 44 | { 45 | //初始化client 46 | locationClient = new AMapLocationClient(context); 47 | locationOption = getDefaultOption(); 48 | //设置定位参数 49 | locationClient.setLocationOption(locationOption); 50 | // 设置定位监听 51 | locationClient.setLocationListener(locationListener); 52 | } 53 | /** 54 | * 默认的定位参数 55 | * @author blueberry 56 | * 57 | */ 58 | private AMapLocationClientOption getDefaultOption(){ 59 | AMapLocationClientOption mOption = new AMapLocationClientOption(); 60 | mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式 61 | mOption.setGpsFirst(false);//可选,设置是否gps优先,只在高精度模式下有效。默认关闭 62 | mOption.setHttpTimeOut(30000);//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效 63 | mOption.setInterval(2000);//可选,设置定位间隔。默认为2秒 64 | mOption.setNeedAddress(true);//可选,设置是否返回逆地理地址信息。默认是true 65 | mOption.setOnceLocation(false);//可选,设置是否单次定位。默认是false 66 | mOption.setOnceLocationLatest(false);//可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用 67 | AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP 68 | mOption.setSensorEnable(false);//可选,设置是否使用传感器。默认是false 69 | mOption.setWifiScan(true); //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差 70 | mOption.setLocationCacheEnable(true); //可选,设置是否使用缓存定位,默认为true 71 | return mOption; 72 | } 73 | 74 | /** 75 | * 定位监听 76 | */ 77 | private AMapLocationListener locationListener = new AMapLocationListener() { 78 | @Override 79 | public void onLocationChanged(AMapLocation location) { 80 | if (null != location) { 81 | if(location.getErrorCode() == 0) { 82 | if(msg != null){ 83 | msg = null; 84 | } 85 | msg = new LocationMsg(); 86 | msg.setMsg_location(location.getAddress()); 87 | msg.setMsg_speed(location.getSpeed()); 88 | 89 | }else{ 90 | msg = new LocationMsg(); 91 | msg.setMsg_location("无法定位"); 92 | msg.setMsg_speed(0); 93 | } 94 | 95 | } else { 96 | msg = new LocationMsg(); 97 | msg.setMsg_location("无法定位"); 98 | msg.setMsg_speed(0); 99 | } 100 | EventBus.getDefault().post(msg);//EventBus发送location speed,MakrkViewManager类负责接收 101 | } 102 | }; 103 | 104 | /** 105 | * 开始定位 106 | * @author blueberry 107 | * 108 | */ 109 | public void startLocation(){ 110 | // 设置定位参数 111 | locationClient.setLocationOption(locationOption); 112 | // 启动定位 113 | locationClient.startLocation(); 114 | } 115 | 116 | /** 117 | * 停止定位 118 | * @author blueberry 119 | * 120 | */ 121 | public void stopLocation(){ 122 | // 停止定位 123 | locationClient.stopLocation(); 124 | } 125 | 126 | /** 127 | * 销毁定位 128 | * @author blueberry 129 | * 130 | */ 131 | public void destroyLocation(){ 132 | if (null != locationClient) { 133 | /** 134 | * 如果AMapLocationClient是在当前Activity实例化的, 135 | * 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy 136 | */ 137 | locationClient.onDestroy(); 138 | locationClient = null; 139 | locationOption = null; 140 | } 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/logic/RecordRepeatManager.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.logic; 2 | 3 | import android.app.Activity; 4 | import android.content.SharedPreferences; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.os.Message; 8 | import android.preference.PreferenceManager; 9 | import android.text.TextUtils; 10 | import android.util.Log; 11 | import android.widget.Toast; 12 | 13 | import com.weibu.recoderboard.entity.CarNumberMsg; 14 | import com.weibu.recoderboard.entity.RecoderMsg; 15 | import com.weibu.recoderboard.util.Constant; 16 | import com.weibu.recoderboard.util.MediaUtils; 17 | 18 | import org.greenrobot.eventbus.EventBus; 19 | import org.greenrobot.eventbus.Subscribe; 20 | import org.greenrobot.eventbus.ThreadMode; 21 | 22 | import java.util.UUID; 23 | 24 | 25 | /** 26 | * Created by blueberry on 2017/7/17. 27 | */ 28 | 29 | public class RecordRepeatManager { 30 | private static RecordRepeatManager mInstance = null; 31 | private Activity context; 32 | private long durion = 25*1000,interval = 500; 33 | private MediaUtils mediaUtils; 34 | private static final int RECORD_START = 0; 35 | private static final int RECORD_STOP = 1; 36 | private Handler mHandler = new Handler(Looper.getMainLooper()){ 37 | @Override 38 | public void handleMessage(Message msg) { 39 | super.handleMessage(msg); 40 | switch (msg.what) 41 | { 42 | case RECORD_START: 43 | mediaUtils.setTargetName(UUID.randomUUID() + ".mp4"); 44 | mediaUtils.record(); 45 | mHandler.sendEmptyMessageDelayed(RECORD_STOP,durion); 46 | break; 47 | case RECORD_STOP: 48 | if( mediaUtils.isRecording()){ 49 | mediaUtils.stopRecordSave();//录制结束 50 | mHandler.sendEmptyMessageDelayed(RECORD_START,interval); 51 | Toast.makeText(context,"保存成功",Toast.LENGTH_LONG).show(); 52 | 53 | }else{ 54 | Toast.makeText(context,"保存失败",Toast.LENGTH_LONG).show(); 55 | } 56 | break; 57 | } 58 | } 59 | }; 60 | 61 | /** 62 | * @param msg 63 | */ 64 | @Subscribe(threadMode = ThreadMode.MAIN) 65 | public void onMainEventBus(RecoderMsg msg) { 66 | Log.i("xxxx","onMainEventBus...getMsg_durion:"+msg.getMsg_durion()); 67 | if(!TextUtils.isEmpty(msg.getMsg_durion())) { 68 | durion = getReateRecoderDurion(msg.getMsg_durion()); 69 | } 70 | } 71 | private long getReateRecoderDurion(String recoder_time) { 72 | int i = Integer.parseInt(recoder_time); 73 | switch (i) { 74 | case 0: 75 | return 1*60*1000;//1分钟 76 | case 1: 77 | return 3*60*1000;//3分钟 78 | case 2: 79 | return 5*60*1000;//5分钟 80 | } 81 | return durion; 82 | } 83 | public static RecordRepeatManager getInstance(Activity context) { 84 | if (mInstance == null) { 85 | synchronized (RecordRepeatManager.class) { 86 | if (mInstance == null) { 87 | mInstance = new RecordRepeatManager(context); 88 | } 89 | } 90 | } 91 | return mInstance; 92 | } 93 | private RecordRepeatManager(Activity activity) { 94 | this.context = activity; 95 | mediaUtils = MediaUtils.getInstance(activity); 96 | EventBus.getDefault().register(this); 97 | } 98 | public RecordRepeatManager setRecordDurion(long recordDurion) 99 | { 100 | this.durion = recordDurion; 101 | return this; 102 | } 103 | 104 | /** 105 | * 目前必须设置为0,才能保证循环录制不漏帧,待确认。 106 | * @param recordInterval 107 | * @return 108 | */ 109 | public RecordRepeatManager setRecordInterval(long recordInterval) 110 | { 111 | this.interval = recordInterval; 112 | return this; 113 | } 114 | 115 | public void startRecordAuto() 116 | { 117 | mHandler.sendEmptyMessageDelayed(RECORD_START,500); 118 | } 119 | 120 | public void stop() 121 | { 122 | mHandler.removeCallbacksAndMessages(null); 123 | EventBus.getDefault().unregister(this); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/util/CameraUtils.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.util; 2 | 3 | import android.annotation.TargetApi; 4 | import android.hardware.Camera; 5 | import android.view.Window; 6 | 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by blueberry on 2017/7/14. 12 | */ 13 | 14 | public class CameraUtils { 15 | private CameraUtils() 16 | { 17 | 18 | } 19 | 20 | public static int getCameraBackId() { 21 | return getCameraId(0); 22 | } 23 | 24 | private static int getCameraId(int type) { 25 | int numberOfCameras = Camera.getNumberOfCameras(); 26 | Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 27 | 28 | for(int i = 0; i < numberOfCameras; ++i) { 29 | Camera.getCameraInfo(i, cameraInfo); 30 | if(cameraInfo.facing == type) { 31 | return i; 32 | } 33 | } 34 | 35 | return -1; 36 | } 37 | 38 | public static int getCameraFrontId() { 39 | return getCameraId(1); 40 | } 41 | 42 | public static int getCameraDisplayOrientation(Window window, int cameraId) { 43 | Camera.CameraInfo info = new Camera.CameraInfo(); 44 | Camera.getCameraInfo(cameraId, info); 45 | int rotation = window.getWindowManager().getDefaultDisplay().getRotation(); 46 | int degrees = 0; 47 | switch(rotation) { 48 | case 0: 49 | degrees = 0; 50 | break; 51 | case 1: 52 | degrees = 90; 53 | break; 54 | case 2: 55 | degrees = 180; 56 | break; 57 | case 3: 58 | degrees = 270; 59 | } 60 | 61 | int result; 62 | if(info.facing == 1) { 63 | result = (info.orientation + degrees) % 360; 64 | result = (360 - result) % 360; 65 | } else { 66 | result = (info.orientation - degrees + 360) % 360; 67 | } 68 | 69 | return result; 70 | } 71 | 72 | public static Camera.Size getCameraPictureSize(Camera camera, int nearResolution) { 73 | return getCameraSize(camera.getParameters().getSupportedPictureSizes(), nearResolution); 74 | } 75 | 76 | private static Camera.Size getCameraSize(List sizes, int nearResolution) { 77 | Camera.Size pre = null; 78 | 79 | Camera.Size size; 80 | for(Iterator var4 = sizes.iterator(); var4.hasNext(); pre = size) { 81 | size = (Camera.Size)var4.next(); 82 | int pixs = size.width * size.height; 83 | if(pixs == nearResolution) { 84 | return size; 85 | } 86 | 87 | if(pixs < nearResolution) { 88 | if(pre == null) { 89 | return size; 90 | } 91 | 92 | int preDis = pre.width * pre.height - nearResolution; 93 | int curDis = nearResolution - pixs; 94 | if(preDis <= curDis) { 95 | return pre; 96 | } 97 | 98 | return size; 99 | } 100 | } 101 | 102 | return pre; 103 | } 104 | 105 | public static Camera.Size getCameraPreviewSize(Camera camera, int nearResolution) { 106 | return getCameraSize(camera.getParameters().getSupportedPreviewSizes(), nearResolution); 107 | } 108 | 109 | 110 | public static Camera.Size getCameraVideoSize(Camera camera, int nearResolution) { 111 | Camera.Parameters parameters = camera.getParameters(); 112 | List sizes = parameters.getSupportedVideoSizes(); 113 | return sizes == null?getCameraSize(parameters.getSupportedPreviewSizes(), nearResolution):getCameraSize(sizes, nearResolution); 114 | } 115 | 116 | public static Camera.Size getOptimalVideoSize(List supportedVideoSizes, 117 | List previewSizes, int w, int h) { 118 | // Use a very small tolerance because we want an exact match. 119 | final double ASPECT_TOLERANCE = 0.1; 120 | double targetRatio = (double) w / h; 121 | 122 | // Supported video sizes list might be null, it means that we are allowed to use the preview 123 | // sizes 124 | List videoSizes; 125 | if (supportedVideoSizes != null) { 126 | videoSizes = supportedVideoSizes; 127 | } else { 128 | videoSizes = previewSizes; 129 | } 130 | Camera.Size optimalSize = null; 131 | 132 | // Start with max value and refine as we iterate over available video sizes. This is the 133 | // minimum difference between view and camera height. 134 | double minDiff = Double.MAX_VALUE; 135 | 136 | // Target view height 137 | int targetHeight = h; 138 | 139 | // Try to find a video size that matches aspect ratio and the target view size. 140 | // Iterate over all available sizes and pick the largest size that can fit in the view and 141 | // still maintain the aspect ratio. 142 | for (Camera.Size size : videoSizes) { 143 | double ratio = (double) size.width / size.height; 144 | if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) 145 | continue; 146 | if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) { 147 | optimalSize = size; 148 | minDiff = Math.abs(size.height - targetHeight); 149 | } 150 | } 151 | 152 | // Cannot find video size that matches the aspect ratio, ignore the requirement 153 | if (optimalSize == null) { 154 | minDiff = Double.MAX_VALUE; 155 | for (Camera.Size size : videoSizes) { 156 | if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) { 157 | optimalSize = size; 158 | minDiff = Math.abs(size.height - targetHeight); 159 | } 160 | } 161 | } 162 | return optimalSize; 163 | } 164 | 165 | /** 166 | * 通过对比得到与宽高比最接近的尺寸(如果有相同尺寸,优先选择) 167 | * 168 | * @param surfaceWidth 169 | * 需要被进行对比的原宽 170 | * @param surfaceHeight 171 | * 需要被进行对比的原高 172 | * @param preSizeList 173 | * 需要对比的预览尺寸列表 174 | * @return 得到与原宽高比例最接近的尺寸 175 | */ 176 | public static Camera.Size getCloselyPreSize(int surfaceWidth, int surfaceHeight, 177 | List preSizeList) { 178 | 179 | //因为预览相机图像需要旋转90度,所以在找相机预览size时切换长宽 180 | int ReqTmpWidth = surfaceHeight; 181 | int ReqTmpHeight = surfaceWidth; 182 | 183 | // 得到与传入的宽高比最接近的size 184 | float reqRatio = ((float) ReqTmpWidth) / ReqTmpHeight; 185 | float curRatio, deltaRatio; 186 | float deltaRatioMin = Float.MAX_VALUE; 187 | Camera.Size retSize = null; 188 | for (Camera.Size size : preSizeList) { 189 | if ((size.width == ReqTmpWidth) && (size.height == ReqTmpHeight)) { 190 | return size; 191 | } 192 | curRatio = ((float) size.width) / size.height; 193 | deltaRatio = Math.abs(reqRatio - curRatio); 194 | if (deltaRatio < deltaRatioMin) { 195 | deltaRatioMin = deltaRatio; 196 | retSize = size; 197 | } 198 | } 199 | 200 | return retSize; 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/util/Constant.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.util; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by blueberry on 2017/7/14. 7 | */ 8 | 9 | public class Constant { 10 | private Constant(){ 11 | 12 | } 13 | public static final String prefs_key_car_number = "car_number"; 14 | public static final String prefs_key_recoder_time = "recoder_time"; 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/util/MediaUtils.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.hardware.Camera; 6 | import android.media.CamcorderProfile; 7 | import android.media.MediaRecorder; 8 | import android.os.Handler; 9 | import android.os.Looper; 10 | import android.util.Log; 11 | import android.view.SurfaceHolder; 12 | import android.view.SurfaceView; 13 | import java.io.File; 14 | import java.io.IOException; 15 | import java.util.List; 16 | 17 | /** 18 | * Created by blueberry on 2017/7/14. 19 | */ 20 | 21 | public class MediaUtils implements SurfaceHolder.Callback { 22 | private static final String TAG = "MediaUtils"; 23 | public static final int MEDIA_VIDEO = 1; 24 | private Activity activity; 25 | private Handler handler= new Handler(Looper.getMainLooper()); 26 | private MediaRecorder mMediaRecorder; 27 | private CamcorderProfile profile; 28 | private Camera mCamera; 29 | private SurfaceView mSurfaceView; 30 | private SurfaceHolder mSurfaceHolder; 31 | private File targetDir; 32 | private String targetName; 33 | private File targetFile; 34 | private int previewWidth, previewHeight; 35 | private int recorderType; 36 | private boolean isRecording; 37 | private int or = 0; 38 | private int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头 39 | 40 | public static final int RESOLUTION_360P = 172800; 41 | public static final int RESOLUTION_480P = 411840; 42 | public static final int RESOLUTION_720P = 921600; 43 | public static final int RESOLUTION_1080P = 2073600; 44 | 45 | private static MediaUtils mInstance = null; 46 | 47 | public static MediaUtils getInstance(Activity context) { 48 | if (mInstance == null) { 49 | synchronized (MediaUtils.class) { 50 | if (mInstance == null) { 51 | mInstance = new MediaUtils(context); 52 | } 53 | } 54 | } 55 | return mInstance; 56 | } 57 | private MediaUtils(Activity activity) { 58 | this.activity = activity; 59 | } 60 | 61 | public void setRecorderType(int type) { 62 | this.recorderType = type; 63 | } 64 | 65 | public void setTargetDir(File file) { 66 | this.targetDir = file; 67 | } 68 | 69 | public void setTargetName(String name) { 70 | this.targetName = name; 71 | } 72 | 73 | public String getTargetFilePath() { 74 | return targetFile.getPath(); 75 | } 76 | 77 | public boolean deleteTargetFile() { 78 | if (targetFile.exists()) { 79 | return targetFile.delete(); 80 | } else { 81 | return false; 82 | } 83 | } 84 | 85 | 86 | public void setSurfaceView(SurfaceView view) { 87 | this.mSurfaceView = view; 88 | mSurfaceHolder = mSurfaceView.getHolder(); 89 | mSurfaceHolder.setFixedSize(previewWidth, previewHeight); 90 | mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 91 | mSurfaceHolder.addCallback(this); 92 | } 93 | public int getPreviewWidth() { 94 | return previewWidth; 95 | } 96 | 97 | public int getPreviewHeight() { 98 | return previewHeight; 99 | } 100 | 101 | public boolean isRecording() { 102 | return isRecording; 103 | } 104 | 105 | public void record() { 106 | Log.i("xxxx","isRecording:"+isRecording); 107 | if (isRecording) { 108 | try { 109 | mMediaRecorder.stop(); 110 | } catch (RuntimeException e) { 111 | targetFile.delete(); 112 | } 113 | releaseMediaRecorder(); 114 | mCamera.lock(); 115 | isRecording = false; 116 | } else { 117 | startRecordThread(); 118 | } 119 | } 120 | 121 | private boolean prepareRecord() { 122 | try { 123 | mMediaRecorder = new MediaRecorder(); 124 | if (recorderType == MEDIA_VIDEO) { 125 | mCamera.unlock(); 126 | mMediaRecorder.setCamera(mCamera); 127 | mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); 128 | mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 129 | // mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 130 | // mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 131 | // // 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错 132 | // // mMediaRecorder.setVideoSize(videoSize.width, videoSize.height); 133 | // mMediaRecorder.setOrientationHint(CameraUtils.getCameraDisplayOrientation(activity.getWindow(),Camera.CameraInfo.CAMERA_FACING_BACK)); 134 | // // 设置录制的视频帧率。必须放在设置编码和格式的后面,否则报错 135 | // mMediaRecorder.setVideoFrameRate(20); 136 | // mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); 137 | // mMediaRecorder.setVideoEncodingBitRate(3500000); 138 | mMediaRecorder.setProfile(profile); 139 | 140 | 141 | } 142 | targetFile = new File(targetDir, targetName); 143 | mMediaRecorder.setOutputFile(targetFile.getPath()); 144 | 145 | } catch (Exception e) { 146 | e.printStackTrace(); 147 | releaseMediaRecorder(); 148 | return false; 149 | } 150 | try { 151 | mMediaRecorder.prepare(); 152 | } catch (IllegalStateException e) { 153 | releaseMediaRecorder(); 154 | return false; 155 | } catch (IOException e) { 156 | releaseMediaRecorder(); 157 | return false; 158 | } 159 | return true; 160 | } 161 | 162 | public void stopRecordSave() { 163 | if (isRecording) { 164 | isRecording = false; 165 | try { 166 | mMediaRecorder.stop(); 167 | } catch (RuntimeException r) { 168 | } finally { 169 | releaseMediaRecorder(); 170 | } 171 | } 172 | } 173 | 174 | public void stopRecordUnSave() { 175 | if (isRecording) { 176 | isRecording = false; 177 | try { 178 | mMediaRecorder.stop(); 179 | } catch (RuntimeException r) { 180 | if (targetFile.exists()) { 181 | //不保存直接删掉 182 | targetFile.delete(); 183 | } 184 | } finally { 185 | releaseMediaRecorder(); 186 | } 187 | if (targetFile.exists()) { 188 | //不保存直接删掉 189 | targetFile.delete(); 190 | } 191 | } 192 | } 193 | 194 | private void startPreView(SurfaceHolder holder) { 195 | if (mCamera == null) { 196 | mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); 197 | } 198 | if (mCamera != null) { 199 | mCamera.setDisplayOrientation(CameraUtils.getCameraDisplayOrientation(activity.getWindow(), Camera.CameraInfo.CAMERA_FACING_BACK)); 200 | //mCamera.setDisplayOrientation(or); 201 | try { 202 | mCamera.setPreviewDisplay(holder); 203 | Camera.Parameters parameters = mCamera.getParameters(); 204 | //从系统相机所支持的size列表中找到与屏幕长宽比最相近的size 205 | //Camera.Size previewSize = CameraUtils.getCloselyPreSize(mSurfaceView.getWidth(),mSurfaceView.getHeight(),parameters.getSupportedPreviewSizes()); 206 | Camera.Size previewSize = CameraUtils.getCameraPreviewSize(mCamera, RESOLUTION_720P); 207 | previewWidth = previewSize.width; 208 | previewHeight = previewSize.height; 209 | parameters.setPreviewSize(previewWidth, previewHeight); 210 | profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); 211 | // 重点,分辨率和比特率 212 | // 分辨率越大视频大小越大,比特率越大视频越清晰 213 | // 清晰度由比特率决定,视频尺寸和像素量由分辨率决定 214 | // 比特率越高越清晰(前提是分辨率保持不变),分辨率越大视频尺寸越大。 215 | profile.videoFrameWidth = previewSize.width; 216 | profile.videoFrameHeight = previewSize.height; 217 | // 这样设置 720p的视频 大小在5M , 可根据自己需求调节 218 | profile.videoBitRate = 2* previewSize.width * previewSize.height; 219 | List focusModes = parameters.getSupportedFocusModes(); 220 | if (focusModes != null) { 221 | for (String mode : focusModes) { 222 | mode.contains("continuous-video"); 223 | parameters.setFocusMode("continuous-video"); 224 | } 225 | } 226 | mCamera.setParameters(parameters); 227 | mCamera.startPreview(); 228 | } catch (IOException e) { 229 | e.printStackTrace(); 230 | } 231 | } 232 | } 233 | 234 | private void releaseMediaRecorder() { 235 | if (mMediaRecorder != null) { 236 | mMediaRecorder.reset(); 237 | mMediaRecorder.release(); 238 | mMediaRecorder = null; 239 | } 240 | } 241 | 242 | private void releaseCamera() { 243 | if (mCamera != null) { 244 | mCamera.release(); 245 | mCamera = null; 246 | } 247 | } 248 | 249 | @Override 250 | public void surfaceCreated(SurfaceHolder holder) { 251 | mSurfaceHolder = holder; 252 | startPreView(holder); 253 | } 254 | 255 | @Override 256 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 257 | 258 | } 259 | 260 | @Override 261 | public void surfaceDestroyed(SurfaceHolder holder) { 262 | if (mCamera != null) { 263 | releaseCamera(); 264 | } 265 | if (mMediaRecorder != null) { 266 | releaseMediaRecorder(); 267 | } 268 | } 269 | 270 | private void startRecordThread() { 271 | 272 | if (prepareRecord()) { 273 | try { 274 | mMediaRecorder.start(); 275 | isRecording = true; 276 | } catch (RuntimeException r) { 277 | releaseMediaRecorder(); 278 | } 279 | }else{ 280 | Log.i("xxxx","prepareRecord false"); 281 | } 282 | } 283 | 284 | } 285 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/util/Utils.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.util; 2 | 3 | import android.content.Context; 4 | import android.content.res.Configuration; 5 | import android.graphics.RectF; 6 | import android.util.DisplayMetrics; 7 | import android.view.View; 8 | 9 | /** 10 | * Created by blueberry on 2017/7/14. 11 | */ 12 | 13 | public class Utils { 14 | 15 | private static Utils mInstance = null; 16 | private Context context; 17 | 18 | public static Utils getInstance(Context context) { 19 | if (mInstance == null) { 20 | synchronized (Utils.class) { 21 | if (mInstance == null) { 22 | mInstance = new Utils(context); 23 | } 24 | } 25 | } 26 | return mInstance; 27 | } 28 | 29 | private Utils(Context context) { 30 | this.context = context; 31 | } 32 | 33 | public int getWidthPixels() { 34 | DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); 35 | Configuration cf = context.getResources().getConfiguration(); 36 | int ori = cf.orientation; 37 | if (ori == Configuration.ORIENTATION_LANDSCAPE) {// 横屏 38 | return displayMetrics.heightPixels; 39 | } else if (ori == Configuration.ORIENTATION_PORTRAIT) {// 竖屏 40 | return displayMetrics.widthPixels; 41 | } 42 | return 0; 43 | } 44 | 45 | public int getHeightPixels() { 46 | DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); 47 | Configuration cf = context.getResources().getConfiguration(); 48 | int ori = cf.orientation; 49 | if (ori == Configuration.ORIENTATION_LANDSCAPE) {// 横屏 50 | return displayMetrics.widthPixels; 51 | } else if (ori == Configuration.ORIENTATION_PORTRAIT) {// 竖屏 52 | return displayMetrics.heightPixels; 53 | } 54 | return 0; 55 | } 56 | 57 | public int dp2px(float dpValue) { 58 | final float scale = context.getResources().getDisplayMetrics().density; 59 | return (int) (dpValue * scale + 0.5f); 60 | } 61 | 62 | public int px2dp(float pxValue) { 63 | final float scale = context.getResources().getDisplayMetrics().density; 64 | return (int) (pxValue / scale + 0.5f); 65 | } 66 | /** 67 | * 得到一个格式化的时间 68 | * 69 | * @param time 时间 毫秒 70 | * 71 | * @return 时:分:秒 72 | */ 73 | public static String getFormatTime(long time) { 74 | time = time/1000; 75 | long second = time % 60; 76 | long minute = (time % 3600) / 60; 77 | long hour = time / 3600; 78 | 79 | // 秒显示两位 80 | String strSecond = ("00" + second).substring(("00" + second).length() - 2); 81 | // 分显示两位 82 | String strMinute = ("00" + minute).substring(("00" + minute).length() - 2); 83 | // 时显示两位 84 | String strHour = ("00" + hour).substring(("00" + hour).length() - 2); 85 | 86 | return strHour + ":" + strMinute + ":" + strSecond; 87 | } 88 | 89 | /** 90 | * 判断触摸是否在view内,不能在onCreate中调用 91 | */ 92 | public static Boolean isTouchContain(View view,float x,float y) { 93 | int[] location = new int[2]; // 获取控件在屏幕中的位置,返回的数组分别为控件左顶点的 x、y 的值 94 | view.getLocationOnScreen(location); 95 | RectF rect = new RectF(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight()); 96 | return rect.contains(x, y); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/viewmanager/IViewManager.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.viewmanager; 2 | 3 | import android.content.Context; 4 | 5 | import com.weibu.recoderboard.MainActivity; 6 | 7 | /** 8 | * Created by blueberry on 2017/7/14. 9 | */ 10 | 11 | public interface IViewManager { 12 | public IViewManager initView(); 13 | public IViewManager initData(); 14 | public void show(); 15 | public void hide(); 16 | public void hideDelay(long delay); 17 | public void showContinue(); 18 | public void stop(); 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/viewmanager/MarkViewManager.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.viewmanager; 2 | 3 | import android.content.SharedPreferences; 4 | import android.preference.Preference; 5 | import android.preference.PreferenceManager; 6 | import android.text.TextUtils; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | import com.weibu.recoderboard.MainActivity; 11 | import com.weibu.recoderboard.R; 12 | import com.weibu.recoderboard.entity.CarNumberMsg; 13 | import com.weibu.recoderboard.entity.LocationMsg; 14 | import com.weibu.recoderboard.util.Constant; 15 | import org.greenrobot.eventbus.EventBus; 16 | import org.greenrobot.eventbus.Subscribe; 17 | import org.greenrobot.eventbus.ThreadMode; 18 | 19 | /** 20 | * Created by blueberry on 2017/7/14. 21 | * 标记(车牌号,位置,天气...)显示管理类,负责数据显示 22 | */ 23 | 24 | public class MarkViewManager implements IViewManager { 25 | 26 | private MainActivity mainActivity; 27 | private TextView tvCarNumber,tvLocation,tvSpeed; 28 | 29 | public MarkViewManager(MainActivity context) 30 | { 31 | this.mainActivity = context; 32 | } 33 | @Override 34 | public MarkViewManager initView() { 35 | tvCarNumber = (TextView) mainActivity.findViewById(R.id.tv_no); 36 | tvLocation = (TextView) mainActivity.findViewById(R.id.tv_location); 37 | tvSpeed = (TextView) mainActivity.findViewById(R.id.tv_speed); 38 | return this; 39 | } 40 | 41 | @Override 42 | public MarkViewManager initData() { 43 | SharedPreferences shp = PreferenceManager.getDefaultSharedPreferences(mainActivity); 44 | String car_number = shp.getString(Constant.prefs_key_car_number,""); 45 | if(!TextUtils.isEmpty(car_number)) { 46 | tvCarNumber.setText("车牌号:"+car_number); 47 | }else{ 48 | hide(); 49 | } 50 | EventBus.getDefault().register(this);//注册EventBus 51 | return this; 52 | } 53 | 54 | @Override 55 | public void show() { 56 | tvCarNumber.setVisibility(View.VISIBLE); 57 | } 58 | 59 | @Override 60 | public void hide() { 61 | tvCarNumber.setVisibility(View.INVISIBLE); 62 | } 63 | 64 | @Override 65 | public void hideDelay(long delay) { 66 | 67 | } 68 | 69 | @Override 70 | public void showContinue() { 71 | 72 | } 73 | 74 | @Override 75 | public void stop() { 76 | EventBus.getDefault().unregister(this);//解注册EventBus 77 | } 78 | 79 | /** 80 | * @param msg 81 | */ 82 | @Subscribe (threadMode = ThreadMode.MAIN) 83 | public void onMainEventBus(CarNumberMsg msg) { 84 | Log.i("xxxx","onMainEventBus...msg:"+msg.getMessage()); 85 | if(!TextUtils.isEmpty(msg.getMessage())) { 86 | tvCarNumber.setText("车牌号:"+ msg.getMessage()); 87 | show(); 88 | } 89 | } 90 | 91 | /** 92 | * @param msg 93 | */ 94 | @Subscribe (threadMode = ThreadMode.MAIN) 95 | public void onMainEventBus(LocationMsg msg) { 96 | if(!TextUtils.isEmpty(msg.getMsg_location())) { 97 | tvLocation.setText("位置:"+ msg.getMsg_location()); 98 | } 99 | 100 | if(!TextUtils.isEmpty(msg.getMsg_location())) { 101 | tvSpeed.setText("速度:"+ msg.getMsg_speed()); 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/viewmanager/RecoderViewManager.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.viewmanager; 2 | 3 | import android.view.View; 4 | import android.widget.Button; 5 | import android.widget.TextView; 6 | import android.widget.Toast; 7 | import android.os.Handler; 8 | import com.weibu.recoderboard.MainActivity; 9 | import com.weibu.recoderboard.R; 10 | import com.weibu.recoderboard.util.MediaUtils; 11 | import com.weibu.recoderboard.util.Utils; 12 | 13 | 14 | /** 15 | * Created by blueberry on 2017/7/14. 16 | * 预留录像按钮,主要做点击事件,延长delay秒消失及其他 17 | */ 18 | 19 | public class RecoderViewManager implements IViewManager,View.OnClickListener{ 20 | 21 | private MainActivity mainActivity; 22 | private Button btn_recoder; 23 | private TextView tv_recoder_time; 24 | private Handler handler = new Handler(); 25 | private long delay; 26 | 27 | private long timer = 0; 28 | private String timeStr = ""; 29 | 30 | private boolean isRecodering = false; 31 | 32 | public RecoderViewManager(MainActivity context) 33 | { 34 | this.mainActivity = context; 35 | } 36 | 37 | @Override 38 | public RecoderViewManager initView() { 39 | btn_recoder = (Button) mainActivity.findViewById(R.id.btn_recoder); 40 | tv_recoder_time = (TextView) mainActivity.findViewById(R.id.tv_recoder_time); 41 | btn_recoder.setOnClickListener(this); 42 | return this; 43 | } 44 | 45 | public RecoderViewManager initData() 46 | { 47 | return this; 48 | } 49 | 50 | @Override 51 | public void show() { 52 | btn_recoder.setVisibility(View.VISIBLE); 53 | } 54 | 55 | @Override 56 | public void hide() { 57 | btn_recoder.setVisibility(View.INVISIBLE); 58 | tv_recoder_time.setVisibility(View.INVISIBLE); 59 | } 60 | 61 | @Override 62 | public void hideDelay(long delay) { 63 | this.delay = delay; 64 | handler.postDelayed(hideR,delay); 65 | } 66 | 67 | @Override 68 | public void showContinue() { 69 | handler.removeCallbacks(hideR); 70 | show(); 71 | hideDelay(delay); 72 | } 73 | 74 | @Override 75 | public void stop() { 76 | isRecodering = false; 77 | handler.removeCallbacks(timeR); 78 | handler.removeCallbacks(hideR); 79 | } 80 | 81 | 82 | @Override 83 | public void onClick(View v) { 84 | switch (v.getId()) 85 | { 86 | case R.id.btn_recoder: 87 | if(isRecodering){ 88 | isRecodering = false; 89 | if(mainActivity.isRecording()){ 90 | mainActivity.stopRecordSave();//录制结束 91 | Toast.makeText(mainActivity,"保存成功",Toast.LENGTH_LONG).show(); 92 | }else{ 93 | Toast.makeText(mainActivity,"保存失败",Toast.LENGTH_LONG).show(); 94 | } 95 | 96 | tv_recoder_time.setVisibility(View.INVISIBLE); 97 | btn_recoder.setBackgroundResource(R.drawable.recoder); 98 | handler.removeCallbacks(timeR); 99 | 100 | }else { 101 | btn_recoder.setBackgroundResource(R.drawable.recoder_stop); 102 | mainActivity.record();//开始录制 103 | isRecodering = true; 104 | tv_recoder_time.setVisibility(View.VISIBLE); 105 | handler.postDelayed(timeR,1*1000); 106 | Toast.makeText(mainActivity,"开始录制",Toast.LENGTH_LONG).show(); 107 | } 108 | break; 109 | } 110 | } 111 | 112 | /** 113 | * 录制时间刷新 114 | */ 115 | private Runnable timeR = new Runnable() { 116 | @Override 117 | public void run() { 118 | timer += 1000; 119 | timeStr = Utils.getFormatTime(timer); 120 | tv_recoder_time.setText(timeStr); 121 | handler.postDelayed(timeR, 1000); 122 | } 123 | }; 124 | 125 | private Runnable hideR = new Runnable() { 126 | @Override 127 | public void run() { 128 | hide(); 129 | } 130 | }; 131 | 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/viewmanager/SettingViewManager.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.viewmanager; 2 | 3 | import android.os.Handler; 4 | import android.view.View; 5 | import android.widget.ImageButton; 6 | import com.weibu.recoderboard.MainActivity; 7 | import com.weibu.recoderboard.R; 8 | 9 | /** 10 | * Created by blueberry on 2017/7/14. 11 | * 设置按钮,主要做点击事件,延长delay秒消失及其他 12 | */ 13 | 14 | public class SettingViewManager implements IViewManager,View.OnClickListener{ 15 | 16 | private MainActivity mainActivity; 17 | private ImageButton ibSetting; 18 | private Handler handler = new Handler(); 19 | private long delay; 20 | public SettingViewManager(MainActivity context) 21 | { 22 | this.mainActivity = context; 23 | } 24 | @Override 25 | public SettingViewManager initView() { 26 | ibSetting = (ImageButton) mainActivity.findViewById(R.id.ib_setting); 27 | ibSetting.setOnClickListener(this); 28 | ibSetting.setAlpha(0.5f); 29 | return this; 30 | } 31 | 32 | @Override 33 | public SettingViewManager initData() { 34 | return this; 35 | } 36 | 37 | @Override 38 | public void show() { 39 | if(!ibSetting.isShown()) 40 | ibSetting.setVisibility(View.VISIBLE); 41 | } 42 | 43 | @Override 44 | public void hide() { 45 | 46 | if(ibSetting.isShown()) 47 | ibSetting.setVisibility(View.INVISIBLE); 48 | } 49 | 50 | @Override 51 | public void hideDelay(long delay) { 52 | this.delay = delay; 53 | handler.postDelayed(delayR,delay); 54 | } 55 | 56 | @Override 57 | public void showContinue() { 58 | handler.removeCallbacks(delayR); 59 | show(); 60 | hideDelay(delay); 61 | } 62 | 63 | @Override 64 | public void stop() { 65 | handler.removeCallbacks(delayR); 66 | } 67 | 68 | private Runnable delayR = new Runnable() { 69 | @Override 70 | public void run() { 71 | hide(); 72 | } 73 | }; 74 | 75 | @Override 76 | public void onClick(View v) { 77 | if(v== ibSetting){ 78 | mainActivity.showSettingLay(); 79 | } 80 | 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/weibu/recoderboard/widget/AlwaysMarqueeTextView.java: -------------------------------------------------------------------------------- 1 | package com.weibu.recoderboard.widget; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.support.annotation.Nullable; 6 | import android.util.AttributeSet; 7 | import android.widget.TextView; 8 | 9 | /** 10 | * Created by user on 2017/7/18. 11 | */ 12 | 13 | public class AlwaysMarqueeTextView extends TextView { 14 | public AlwaysMarqueeTextView(Context context) { 15 | super(context,null); 16 | } 17 | 18 | public AlwaysMarqueeTextView(Context context, @Nullable AttributeSet attrs) { 19 | super(context, attrs,0); 20 | } 21 | 22 | public AlwaysMarqueeTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 23 | super(context, attrs, defStyleAttr); 24 | } 25 | 26 | @Override 27 | public boolean isFocused() { 28 | return true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libGNaviData.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/arm64-v8a/libGNaviData.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libGNaviMap.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/arm64-v8a/libGNaviMap.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libGNaviMapex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/arm64-v8a/libGNaviMapex.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libGNaviSearch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/arm64-v8a/libGNaviSearch.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libGNaviUtils.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/arm64-v8a/libGNaviUtils.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libRoadLineRebuildAPI.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/arm64-v8a/libRoadLineRebuildAPI.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libGNaviData.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi-v7a/libGNaviData.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libGNaviMap.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi-v7a/libGNaviMap.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libGNaviMapex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi-v7a/libGNaviMapex.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libGNaviSearch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi-v7a/libGNaviSearch.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libGNaviUtils.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi-v7a/libGNaviUtils.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libRoadLineRebuildAPI.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi-v7a/libRoadLineRebuildAPI.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/libGNaviData.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi/libGNaviData.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/libGNaviMap.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi/libGNaviMap.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/libGNaviMapex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi/libGNaviMapex.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/libGNaviSearch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi/libGNaviSearch.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/libGNaviUtils.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi/libGNaviUtils.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/libRoadLineRebuildAPI.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/armeabi/libRoadLineRebuildAPI.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libGNaviData.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86/libGNaviData.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libGNaviMap.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86/libGNaviMap.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libGNaviMapex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86/libGNaviMapex.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libGNaviSearch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86/libGNaviSearch.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libGNaviUtils.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86/libGNaviUtils.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86/libRoadLineRebuildAPI.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86/libRoadLineRebuildAPI.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86_64/libGNaviData.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86_64/libGNaviData.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86_64/libGNaviMap.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86_64/libGNaviMap.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86_64/libGNaviMapex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86_64/libGNaviMapex.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86_64/libGNaviSearch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86_64/libGNaviSearch.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86_64/libGNaviUtils.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86_64/libGNaviUtils.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/x86_64/libRoadLineRebuildAPI.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/jniLibs/x86_64/libRoadLineRebuildAPI.so -------------------------------------------------------------------------------- /app/src/main/res/animator/slide_in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/animator/slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/res/drawable-hdpi/icon_setting.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/res/drawable-hdpi/record.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/recording.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/res/drawable-hdpi/recording.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/recordpressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/res/drawable-hdpi/recordpressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/res/drawable-hdpi/stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/stoppressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danxinzhicheng/RecoderBoard/bc6f42f0625d3396517497608a180fac7555cd93/app/src/main/res/drawable-hdpi/stoppressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/recoder.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/recoder_stop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/lay_mark.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 20 | 21 | 31 | 32 | 42 | 43 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/lay_recoder.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 |