diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..58e06d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,59 @@ + +### Android template +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle/ +build/ +androidTest/ +test/ +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Intellij +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/dictionaries +.idea/libraries + +# Keystore files +*.jks + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..4fb78b8 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,33 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 25 + buildToolsVersion "25.0.2" + defaultConfig { + applicationId "jaygoo.wavelineview" + minSdkVersion 16 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + + compile 'com.android.support:appcompat-v7:25.3.1' + testCompile 'junit:junit:4.12' + compile project(path: ':library') + compile 'com.github.Jay-Goo:AndroidMP3Recorder:v1.0.7' + //内存泄漏检测 + debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' + releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' + testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..7e3f83c --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/mac/Library/Android/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f9d1c81 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/jaygoo/wavelineview/App.java b/app/src/main/java/jaygoo/wavelineview/App.java new file mode 100644 index 0000000..80fb9dc --- /dev/null +++ b/app/src/main/java/jaygoo/wavelineview/App.java @@ -0,0 +1,25 @@ +package jaygoo.wavelineview; + +import android.app.Application; + +import com.squareup.leakcanary.LeakCanary; + + +/** + * ================================================ + * 作 者:JayGoo + * 版 本: + * 创建日期:2017/7/28 + * 描 述: + * ================================================ + */ +public class App extends Application { + @Override + public void onCreate() { + super.onCreate(); + if (LeakCanary.isInAnalyzerProcess(this)) { + return; + } + LeakCanary.install(this); + } +} diff --git a/app/src/main/java/jaygoo/wavelineview/MainActivity.java b/app/src/main/java/jaygoo/wavelineview/MainActivity.java new file mode 100644 index 0000000..9231e2b --- /dev/null +++ b/app/src/main/java/jaygoo/wavelineview/MainActivity.java @@ -0,0 +1,60 @@ +package jaygoo.wavelineview; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +import jaygoo.widget.wlv.WaveLineView; + +public class MainActivity extends AppCompatActivity { + + private WaveLineView waveLineView; + private WaveMp3Recorder waveMp3Recorder; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); +// waveLineView = (WaveLineView) findViewById(R.id.waveLineView); + waveMp3Recorder = (WaveMp3Recorder) findViewById(R.id.waveLineView); + findViewById(R.id.startBtn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!waveMp3Recorder.isRecording()){ + waveMp3Recorder.startRecord(); + } + } + }); + + findViewById(R.id.stopBtn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (waveMp3Recorder.isRecording()){ + waveMp3Recorder.stopRecord(true); + } + } + }); + } + + + @Override + protected void onResume() { + super.onResume(); +// waveLineView.onResume(true); + waveMp3Recorder.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); +// waveLineView.onPause(); + waveMp3Recorder.onPause(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); +// waveLineView.release(); +// waveMp3Recorder.release(); + } +} diff --git a/app/src/main/java/jaygoo/wavelineview/WaveMp3Recorder.java b/app/src/main/java/jaygoo/wavelineview/WaveMp3Recorder.java new file mode 100644 index 0000000..637e4b9 --- /dev/null +++ b/app/src/main/java/jaygoo/wavelineview/WaveMp3Recorder.java @@ -0,0 +1,176 @@ +package jaygoo.wavelineview; + +import android.content.Context; +import android.os.Environment; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Log; + +import com.czt.mp3recorder.MP3Recorder; + +import java.io.File; + +import jaygoo.widget.wlv.WaveLineView; + +/** + * ================================================ + * 作 者:JayGoo + * 版 本: + * 创建日期:2017/7/18 + * 描 述: + * ================================================ + */ +public class WaveMp3Recorder extends WaveLineView { + private String RECORD_FILE_DIR = Environment.getExternalStorageDirectory()+"/"; + private String recordFileName = "WaveLineViewTest.mp3"; + private MP3Recorder mp3Recorder; + private long maxRecordTime = 1000 * 60 * 60 * 24; + private long recordTime = 0; + private int UPDATE_TIME = 200; + private OnRecordStateChangeListener mOnRecordStateChangeListener; + private Handler mHandler = new Handler(); + + public WaveMp3Recorder(Context context) { + this(context,null); + } + + public WaveMp3Recorder(Context context, AttributeSet attrs) { + this(context, attrs,0); + } + + public WaveMp3Recorder(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initRecorder(); + } + + private void updateRecordingUI(){ + if (mp3Recorder != null) { + setVolume(100 * mp3Recorder.getVolume() / mp3Recorder.getMaxVolume()); + } + } + + private void updateStopRecordUI(){ + stopAnim(); + } + + private void updateStartRecordUI(){ + startAnim(); + } + + /** + * 录音更新进度条 + */ + private Runnable mRecordProgressTask = new Runnable() { + public void run() { + + //录音时间超出最大时间,自动停止 + if (recordTime > maxRecordTime){ + stopRecord(true); + }else { + updateRecordingUI(); + if (mHandler != null) { + mHandler.postDelayed(mRecordProgressTask, UPDATE_TIME); + } + } + } + }; + + public void initRecorder(){ + File recordFile = new File(RECORD_FILE_DIR, recordFileName); + mp3Recorder = new MP3Recorder(recordFile); + mp3Recorder.setDefaultLameMp3BitRate(96); + } + + public void startRecording(){ + try { + mp3Recorder.start(); + if (mHandler != null) { + mHandler.post(mRecordProgressTask); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + //停止录音按钮状态 + public void stopRecord(boolean isFromUser){ + if (mHandler != null) { + mHandler.removeCallbacksAndMessages(null); + } + try { + recordTime = 0; + updateStopRecordUI(); + if (mp3Recorder != null) { + mp3Recorder.stop(); + } + }catch (Exception e){ + e.printStackTrace(); + } + + + if (mOnRecordStateChangeListener != null){ + mOnRecordStateChangeListener.onStopRecord(getRecordFile(),isFromUser); + } + } + + public void stopRecord(){ + stopRecord(false); + } + + //开始录音 + public void startRecord(){ + updateStartRecordUI(); + try { + mp3Recorder.start(); + if (mHandler != null) { + mHandler.post(mRecordProgressTask); + } + } catch (Exception e) { + e.printStackTrace(); + } + + if (mOnRecordStateChangeListener != null){ + mOnRecordStateChangeListener.onStartRecord(); + } + } + + //是否在录音 + public boolean isRecording(){ + if (mp3Recorder != null){ + return mp3Recorder.isRecording(); + } + return false; + } + + //设置录音的最大时间 + public void setMaxRecordTime(long millis){ + maxRecordTime = millis; + } + + //获取录音文件 + public File getRecordFile(){ + return new File(RECORD_FILE_DIR, recordFileName); + } + + public String getRecordFilePath(){ + return RECORD_FILE_DIR + "/"+recordFileName; + } + + public MP3Recorder getMp3Recorder(){ + return mp3Recorder; + } + + + //录音状态监听 + public interface OnRecordStateChangeListener{ + void onStartRecord(); + void onStopRecord(File recordFile, boolean isFromUser); + } + + public void setOnRecordStateChangeListener(OnRecordStateChangeListener listener){ + mOnRecordStateChangeListener = listener; + } + +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4c19277 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + +