Code Monkey home page Code Monkey logo

naraeaudiorecorder's Introduction

NaraeAudioRecorder

Download Android Arsenal

AudioRecorder for Android powered by Kotlin.

Key Features

  • Easy to use API
  • Record on various format
    • core: pcm, wav
    • ffmpeg-recorder: mp3, m4a, wma, flac, aac
  • Pause & Resume recording
  • Integrated timer is provide maxAvailableTime feature
  • Remove background noise using NoiseSuppressor API
  • 100% write in Kotlin, but has Java Compatible
  • Detect amount of time of Silent

Import

It distributed on JCenter, but sometime it's not available.

repositories {
    maven { url "https://dl.bintray.com/windsekirun/maven/" }
}

Core

Core module will contain most feature and two format. 'pcm' and 'wav'

implementation 'com.github.WindSekirun.NaraeAudioRecorder:core:1.3.0'

FFmpeg-Recorder

FFmpeg-Recorder will contain five format, 'mp3', 'm4a', 'wma', 'flac', 'aac'

This module will increase Final APK Size about 20MB. You can reduce APK Size by this guide

implementation 'nl.bravobit:android-ffmpeg:1.1.5'
implementation 'com.github.WindSekirun.NaraeAudioRecorder:ffmpeg-recorder:1.3.0'

Usages

Core

Initialization

 val audioRecorder = NaraeAudioRecorder()
 val destFile = File(Environment.getExternalStorageDirectory(), "/NaraeAudioRecorder/$fileName$extensions")
 audioRecorder.create() {
            this.destFile = destFile
 }

Define instance of 'NaraeAudioRecorder' and create file and provide with NaraeAudioRecorder.create is fine.

If you want use NoiseSuppressor, define instance of NoiseAudioSource and provide with NaraeAudioRecorder.create.

val recordConfig = AudioRecordConfig.defaultConfig()
val audioSource = NoiseAudioSource(recordConfig)
audioRecorder.create() {
          this.destFile = this.destFile
          this.recordConfig = recordConfig
          this.audioSource = audioSource
}

Initialization in Java

This is full sample of 'initialization in Java'. other feature is same.

File destFile = new File(getContext().getExternalFilesDir(null) + String.format("/recorder/%s.mp3", fileName));
destFile.getParentFile().mkdirs();

mAudioRecorder.checkPermission(getContext());
mAudioRecorder.create(FFmpegRecordFinder.class, config -> {
    config.setDestFile(destFile);
    config.setDebugMode(true);
    config.setTimerCountListener((currentTime, maxTime) -> { 
    });
            
    return null;
});

FFmpegAudioRecorder ffmpegAudioRecorder = (FFmpegAudioRecorder) mAudioRecorder.getAudioRecorder();
ffmpegAudioRecorder.setContext(getContext());
ffmpegAudioRecorder.setOnConvertStateChangeListener(state -> {
    if (state == FFmpegConvertState.SUCCESS) {
        mRecordedPath = destFile.getPath();
    }
});

Permission

Starting from 1.2.0, if permission isn't granted, NaraeAudioRecorder will throw RuntimeException.

  • RECORD_AUDIO
  • WRITE_EXTERNAL_STORAGE
  • READ_EXTERNAL_STORAGE

So make sure grant proper permissions before using startRecording function.

Start / Stop / Pause / Resume

audioRecorder.startRecording(Context)
audioRecorder.stopRecording()
audioRecorder.pauseRecording()
audioRecorder.resumeRecording()

Custom config of AudioRecord

You can custom config of AudioRecord with AudioRecordConfig

fun defaultConfig() = AudioRecordConfig(MediaRecorder.AudioSource.MIC,
                AudioFormat.ENCODING_PCM_16BIT,
                AudioFormat.CHANNEL_IN_MONO,
                AudioConstants.FREQUENCY_44100)

Listen about state changes of record

audioRecorder.setOnRecordStateChangeListener(OnRecordStateChangeListener)

Set maxAvailableTime & Listen about changes of timer

audioRecorder.create(FFmpegRecordFinder::class.java) {
          ...
          this.maxAvailableMillis = TimeUnit.SECONDS.toMillis(20)
          this.timerCountListener = { currentTime, maxTime -> }
}

If you want use accuracy, define refreshTimerMillis in create section will be help for you. Default is 50.

FFmpeg-recorder

Using FFmpeg-recorder will need some additional info.

audioRecorder.create(FFmpegRecordFinder::class.java) {
            this.destFile = this.destFile
            this.recordConfig = recordConfig
            this.audioSource = audioSource
}

val ffmpegAudioRecorder: FFmpegAudioRecorder = audioRecorder.getAudioRecorder() as? FFmpegAudioRecorder ?: return
ffmpegAudioRecorder.setContext(this)

In parameters of create, use FFmpegRecordFinder::class.java to determine proper recorder with destFile .

FFmpeg-recorder uses WavAudioRecorder internally, recording in wav and convert them to desire format using FFmpeg command.

Change config of FFmpeg

You can custom config of FFmpeg using this options.

ffmpegAudioRecorder.setConvertConfig(FFmpegConvertConfig)

Default value is fun defaultConfig() = FFmpegConvertConfig(bitRate = FFmpegBitRate.def, samplingRate = FFmpegSamplingRate.ORIGINAL, mono = true).

Listen about state changes of convert

ffmpegAudioRecorder.setOnConvertStateChangeListener(OnConvertStateChangeListener)

Sample Application

Code

License

Core

Copyright 2019, WindSekirun (DongGil, Seo)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

FFmpeg-recorder

naraeaudiorecorder's People

Contributors

espertus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

naraeaudiorecorder's Issues

stop() called on an uninitialized AudioRecord.

java.lang.IllegalStateException: stop() called on an uninitialized AudioRecord.
        at android.media.AudioRecord.stop(AudioRecord.java:1041)
        at com.github.windsekirun.naraeaudiorecorder.writer.DefaultRecordWriter.stopRecording(DefaultRecordWriter.kt:34)
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder.stopRecording(DefaultAudioRecorder.kt:55)
        at com.github.windsekirun.naraeaudiorecorder.recorder.WavAudioRecorder.stopRecording(WavAudioRecorder.kt:15)
        at com.github.windsekirun.naraeaudiorecorder.ffmpeg.FFmpegAudioRecorder.stopRecording(FFmpegAudioRecorder.kt:41)
        at com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.stopRecording(NaraeAudioRecorder.kt:111)
        at android.view.View.performClick(View.java:7352)
        at android.view.View.performClickInternal(View.java:7318)
        at android.view.View.access$3200(View.java:846)
        at android.view.View$PerformClick.run(View.java:27801)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7045)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)

Sample app crashes due to unrequested permissions (API 23+)

I forked the repo and tried running it unchanged on a Pixel 2 running Android 10. The sample app crashed when I clicked on the Start button. The log showed that this was because some of the permissions were ungranted. On Marshmallow and later, ActivityCompat.requestPermissions() must be called.

resumeRecording() not working

I tried your app example but the Resume function is not working.
The final audio file is composed only of the part recorded before the pause. If I resume recording, the audio is ignored.
Tried on Android 9 and 10

Not an issue but Questions

  1. Can I use it in a pure Java project in Android
  2. Which output is the smallest in size
  3. I like your library cuz of silence detection, so on silence can I like save the audio previously recorded?
  4. Can I like add timer? Like maxRecording time?

I saw in your documentation but it's not quite clear

Record Audio even in silence?

Currently if there is silence detected the audio simply doesnt records, tried implementing onSilenceDetected listener but nothing happened, how can i record audio even if there is silence.

crash when stop

hi, i got crash when stop record, using the example
here is the log

2021-04-14 02:02:20.531 9281-9281/com.github.windsekirun.naraeaudiorecorder.sample E/NaraeAudioRecorder: stop() called on an uninitialized AudioRecord.
2021-04-14 02:02:20.534 9281-9281/com.github.windsekirun.naraeaudiorecorder.sample E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.github.windsekirun.naraeaudiorecorder.sample, PID: 9281
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:606)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:596)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 
     Caused by: java.io.FileNotFoundException: /storage/emulated/0/NaraeAudioRecorder/2021-04-14 02:02:14.mp3: open failed: EPERM (Operation not permitted)
        at libcore.io.IoBridge.open(IoBridge.java:492)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder$outputStream$2.invoke(DefaultAudioRecorder.kt:18)
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder$outputStream$2.invoke(DefaultAudioRecorder.kt:13)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder.getOutputStream(Unknown Source:7)
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder.stopRecording(DefaultAudioRecorder.kt:56)
        at com.github.windsekirun.naraeaudiorecorder.recorder.WavAudioRecorder.stopRecording(WavAudioRecorder.kt:15)
        at com.github.windsekirun.naraeaudiorecorder.ffmpeg.FFmpegAudioRecorder.stopRecording(FFmpegAudioRecorder.kt:41)
        at com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.stopRecording(NaraeAudioRecorder.kt:105)
        at com.github.windsekirun.naraeaudiorecorder.sample.MainActivity.clickStop(MainActivity.kt:143)
        at com.github.windsekirun.naraeaudiorecorder.sample.databinding.MainActivityBindingImpl$OnClickListenerImpl1.onClick(MainActivityBindingImpl.java:320)
        at android.view.View.performClick(View.java:8160)
        at android.widget.TextView.performClick(TextView.java:16219)
        at android.view.View.performClickInternal(View.java:8137)
        at android.view.View.access$3700(View.java:888)
        at android.view.View$PerformClick.run(View.java:30236)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:8506)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:596) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 
     Caused by: android.system.ErrnoException: open failed: EPERM (Operation not permitted)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8367)
        at libcore.io.IoBridge.open(IoBridge.java:478)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236) 
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186) 
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder$outputStream$2.invoke(DefaultAudioRecorder.kt:18) 
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder$outputStream$2.invoke(DefaultAudioRecorder.kt:13) 
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) 
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder.getOutputStream(Unknown Source:7) 
        at com.github.windsekirun.naraeaudiorecorder.recorder.DefaultAudioRecorder.stopRecording(DefaultAudioRecorder.kt:56) 
        at com.github.windsekirun.naraeaudiorecorder.recorder.WavAudioRecorder.stopRecording(WavAudioRecorder.kt:15) 
        at com.github.windsekirun.naraeaudiorecorder.ffmpeg.FFmpegAudioRecorder.stopRecording(FFmpegAudioRecorder.kt:41) 
        at com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.stopRecording(NaraeAudioRecorder.kt:105) 
        at com.github.windsekirun.naraeaudiorecorder.sample.MainActivity.clickStop(MainActivity.kt:143) 
        at com.github.windsekirun.naraeaudiorecorder.sample.databinding.MainActivityBindingImpl$OnClickListenerImpl1.onClick(MainActivityBindingImpl.java:320) 
        at android.view.View.performClick(View.java:8160) 
        at android.widget.TextView.performClick(TextView.java:16219) 
        at android.view.View.performClickInternal(View.java:8137) 
        at android.view.View.access$3700(View.java:888) 
        at android.view.View$PerformClick.run(View.java:30236) 
        at android.os.Handler.handleCallback(Handler.java:938) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:246) 
        at android.app.ActivityThread.main(ActivityThread.java:8506) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:596) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 

android 11

Bitrate not changing

Why is bitrate configuration is -sample_fmt and not -b:a ?

For example when I use FFmpegBitRate values nothing changes, the bitrate is always 64k.
If I use:
commandBuilder.addAll(listOf("-b:a", "320k"))
The bitrate is changing.

What should I do to change the bitrate without forking the repository and change it manually?

Persmission check Issue

java.lang.NoClassDefFoundError: Failed resolution of: Lpyxis/uzuki/live/richutilskt/utils/RPermission;
	at com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.requestPermission(NaraeAudioRecorder.kt:184)
	at com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.checkPermission(NaraeAudioRecorder.kt:72)
	at com.dewarder.holdinglibrary.HoldingButtonLayout.notifyOnBeforeExpand(HoldingButtonLayout.java:467)
	at com.dewarder.holdinglibrary.HoldingButtonLayout.access$200(HoldingButtonLayout.java:44)
	at com.dewarder.holdinglibrary.HoldingButtonLayout$DrawableListener.onBeforeExpand(HoldingButtonLayout.java:507)
	at com.dewarder.holdinglibrary.HoldingDrawable.notifyOnBeforeExpand(HoldingDrawable.java:375)
	at com.dewarder.holdinglibrary.HoldingDrawable.expand(HoldingDrawable.java:152)
	at com.dewarder.holdinglibrary.HoldingButtonLayout.onTouchEvent(HoldingButtonLayout.java:232)
	at android.view.View.dispatchTouchEvent(View.java:13471)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3216)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2888)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2845)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2845)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2845)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2845)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2845)
	at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
	at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2845)
	at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:697)
	at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1879)
	at android.app.Activity.dispatchTouchEvent(Activity.java:3487)
	at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
	at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:655)
	at android.view.View.dispatchPointerEvent(View.java:13719)
	at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6134)
	at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5912)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5361)
	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5414)
	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5380)
	at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5539)
	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5388)
	at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5596)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5361)
	at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5414)
	at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5380)
	at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5388)
	at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5361)
	at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8423)
	at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8356)
	at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8309)
	at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8538)
	at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:198)
	at android.os.MessageQueue.nativePollOnce(Native Method)
	at android.os.MessageQueue.next(MessageQueue.java:326)
	at android.os.Looper.loop(Looper.java:181)
	at android.app.ActivityThread.main(ActivityThread.java:7076)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
Caused by: java.lang.ClassNotFoundException: Didn't find class "pyxis.uzuki.live.richutilskt.utils.RPermission" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.zedney.camion-7RgD9tCfogK-IFMK_0WTOQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.zedney.camion-7RgD9tCfogK-IFMK_0WTOQ==/lib/arm64, /system/lib64]]
	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
	... 55 more

my gradle file config

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 29
    buildToolsVersion '29.0.2'
    defaultConfig {
        applicationId "com********"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 8
        versionName '0.0.0.1'
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
        dexOptions {
            javaMaxHeapSize "4g"
        }

        buildConfigField "String", "G_API_KEY", "\"******\""
        versionNameSuffix = '.PreAlpha'
    }
    buildTypes {
        release {
            buildConfigField "String", "URL_API", "\"*****\""
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug {
            buildConfigField "String", "URL_API", "\"******\""
        }
    }

    buildTypes.each {
        it.buildConfigField 'String', 'APP_ID', APP_ID
        it.buildConfigField 'String', 'AUTH_KEY', AUTH_KEY
        it.buildConfigField 'String', 'AUTH_SECRET', AUTH_SECRET
        it.buildConfigField 'String', 'ACCOUNT_KEY', ACCOUNT_KEY
    }

    dataBinding {
        enabled = true
    }
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
    dexOptions {
        javaMaxHeapSize "4g"
        preDexLibraries true
        dexInProcess = true
    }
    aaptOptions {
        additionalParameters "--no-version-vectors"
    }
    productFlavors {
    }
}

kapt {
    generateStubs = true
    correctErrorTypes = true
}

sourceSets {
    main {
        java {
            srcDir "${buildDir}/generated/source/kapt/main"
        }
    }
    test {
        java {
            srcDir 'src/test/java'
        }
    }
}


dependencies {

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
    implementation 'androidx.vectordrawable:vectordrawable:1.1.0-rc01'
    implementation 'androidx.core:core-ktx:1.2.0-alpha03'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.1.0-beta03'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
    implementation 'com.android.support:multidex:1.0.3'
    kapt 'com.android.databinding:compiler:3.2.0-alpha10'

    // --> additional

    kapt "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    kapt 'com.android.databinding:compiler:3.2.0-alpha10'
    implementation 'com.intuit.sdp:sdp-android:1.0.6'
    implementation 'com.intuit.ssp:ssp-android:1.0.6'
    implementation 'com.hbb20:ccp:2.3.1'
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    kapt 'com.github.bumptech.glide:compiler:4.9.0'
    implementation 'com.nex3z:flow-layout:1.3.0'
    implementation 'com.github.smarteist:autoimageslider:1.3.2'
    implementation 'com.daimajia.easing:library:2.1@aar'
    implementation 'com.daimajia.androidanimations:library:2.3@aar'
    implementation 'de.hdodenhof:circleimageview:3.0.1'
    implementation(project(':leku')) {
        exclude group: 'com.google.android.gms'
        exclude group: 'androidx.appcompat'
        exclude group: 'com.google.android.libraries.places'
    }
    implementation("com.github.esafirm.android-image-picker:imagepicker:2.1.0", {
        exclude group: 'com.github.bumptech.glide', module: 'glide'
    })
    implementation 'com.github.chrisbanes:PhotoView:2.3.0'
    implementation 'com.dewarder:holdingbutton:0.1.3'
    // additional <---

    // chat <---
    implementation "com.quickblox:quickblox-android-sdk-chat:$rootProject.qbSdkVersion"
    implementation "com.quickblox:quickblox-android-sdk-content:$rootProject.qbSdkVersion"
    implementation "com.quickblox:quickblox-android-sdk-messages:$rootProject.qbSdkVersion"
    implementation 'com.github.stfalcon:chatkit:0.3.3'
    implementation 'com.github.siyamed:android-shape-imageview:0.9.+@aar'
    // ---> chat

    // audio recording <---
    implementation 'com.github.WindSekirun.NaraeAudioRecorder:core:1.1.0'
    implementation 'nl.bravobit:android-ffmpeg:1.1.5'
    implementation 'com.github.WindSekirun.NaraeAudioRecorder:ffmpeg-recorder:1.1.0'
    // ---> audio recording

    // --> google
    implementation 'com.google.android.gms:play-services-base:17.1.0'
    implementation 'com.google.android.gms:play-services-gcm:17.0.0'
    implementation 'com.google.android.gms:play-services-auth:17.0.0'
    implementation 'com.google.android.gms:play-services-location:17.0.0'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    implementation 'com.google.android.libraries.places:places-compat:2.0.0'
    implementation 'com.google.android.material:material:1.1.0-alpha09'
    implementation 'com.google.firebase:firebase-core:17.2.0'
    implementation 'com.google.firebase:firebase-auth:19.0.0'
    implementation 'com.google.firebase:firebase-messaging:20.0.0'
    implementation 'com.google.firebase:firebase-crash:16.2.1'
    // google <---

    // ----> networking
    implementation 'com.squareup.retrofit2:retrofit:2.6.1'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
    implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.12.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.2.11'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    implementation 'com.patloew.rxlocation:rxlocation:1.0.5'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.10.0.pr1'
    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.10.0.pr1'
    // networking <----


    testImplementation 'junit:junit:4.13-beta-3'
    androidTestImplementation 'androidx.test:runner:1.3.0-alpha02'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha02'
}
apply plugin: 'com.google.gms.google-services'

Audio Preview

I can't play audio before calling stopRecording(), its possible to play audio before stopRecording? like an audio preview before stopping the recording.

for android 13 , permission issues

java.lang.RuntimeException: RECORD_AUDIO, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE will be needed for recording audio.
at pereira.agnaldo.audiorecorder.core.src.main.java.com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.startRecording(NaraeAudioRecorder.kt:89)
at pereira.agnaldo.audiorecorder.AudioRecorderView.startRecordAudio(AudioRecorderView.kt:205)

Failed resolution of: Lio/reactivex/Observable

Please, make library more modular, remove RxJava and RichUtilsKt

Process: com.askme.android.client, PID: 22483
    java.lang.NoClassDefFoundError: Failed resolution of: Lio/reactivex/Observable;
        at com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.startTimer(NaraeAudioRecorder.kt:220)
        at com.github.windsekirun.naraeaudiorecorder.NaraeAudioRecorder.startRecording(NaraeAudioRecorder.kt:100)

Remove RichUtilsKt and changes in permission capability

RichUtilsKt appears to be not necessary and proceeds with deletion.

So, Removing RichUtilsKt (and permission capability) will make some changes.

  • Remove 'RichUtilsKt' dependency from build.gradle
  • Remove 'checkPermission()' function in NaraeAudioRecorder
  • Adding Context parameters into startRecording() function. You don't get permissions automatically, but you still need to get three permissions, so use checkSelfPermission to check them. (RECORD_AUDIO, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE)
  • If permission isn't granted, library will throw RuntimeException(RECORD_AUDIO, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE will needed for recording audio)

This changes will deploy as 1.2.0.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.