From f349ff4c1a87205f268b1624b91d792234ba1738 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 13 Mar 2016 13:44:28 +0300 Subject: [PATCH 1/3] codec re arrange . --- .../audiorecorder/encoders/Format3GP.java | 22 +++++ .../audiorecorder/encoders/FormatM4A.java | 98 +----------------- .../axet/audiorecorder/encoders/MuxerMP4.java | 99 +++++++++++++++++++ 3 files changed, 125 insertions(+), 94 deletions(-) create mode 100755 app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java create mode 100755 app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java new file mode 100755 index 0000000..29ed709 --- /dev/null +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java @@ -0,0 +1,22 @@ +package com.github.axet.audiorecorder.encoders; + +import android.annotation.TargetApi; +import android.media.MediaFormat; + +import java.io.File; + +@TargetApi(21) +public class Format3GP extends ContainerMP4 { + + public Format3GP(EncoderInfo info, File out) { + final int kBitRates[] = {6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850}; + + MediaFormat format = new MediaFormat(); + format.setString(MediaFormat.KEY_MIME, "audio/amr-wb"); + format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate); + format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels); + format.setInteger(MediaFormat.KEY_BIT_RATE, 23850); // set maximum + + create(info, format, out); + } +} diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java index b085260..a01e829 100755 --- a/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java @@ -1,112 +1,22 @@ package com.github.axet.audiorecorder.encoders; import android.annotation.TargetApi; -import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; -import android.media.MediaMuxer; import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; @TargetApi(21) -public class FormatM4A implements Encoder { - EncoderInfo info; - MediaCodec encoder; - MediaMuxer muxer; - int audioTrackIndex; - long NumSamples; - - public FormatM4A() { - } +public class FormatM4A extends ContainerMP4 { public FormatM4A(EncoderInfo info, File out) { - this.info = info; - MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm"); format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels); - format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024); + format.setInteger(MediaFormat.KEY_BIT_RATE, 64000); - try { - encoder = MediaCodec.createEncoderByType("audio/mp4a-latm"); - encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); - encoder.start(); - - muxer = new MediaMuxer(out.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); - } catch (IOException e) { - throw new RuntimeException(e); - } + create(info, format, out); } - - public void encode(short[] buf) { - int len = buf.length * 2; - int inputIndex = encoder.dequeueInputBuffer(-1); - if (inputIndex >= 0) { - ByteBuffer input = encoder.getInputBuffer(inputIndex); - input.clear(); - for (int i = 0; i < buf.length; i++) - input.putShort(buf[i]); - encoder.queueInputBuffer(inputIndex, 0, len, getCurrentTimeStamp(), 0); - } - - NumSamples += buf.length / info.channels; - - encode(); - } - - void encode() { - MediaCodec.BufferInfo outputInfo = new MediaCodec.BufferInfo(); - int outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0); - if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { - audioTrackIndex = muxer.addTrack(encoder.getOutputFormat()); - muxer.start(); - } - - while (outputIndex >= 0) { - ByteBuffer output = encoder.getOutputBuffer(outputIndex); - output.position(outputInfo.offset); - output.limit(outputInfo.offset + outputInfo.size); - -// byte[] out = new byte[outputInfo.size]; -// output.get(out); - - muxer.writeSampleData(audioTrackIndex, output, outputInfo); - - encoder.releaseOutputBuffer(outputIndex, false); - outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0); - } - } - - public void close() { - end(); - encode(); - - encoder.stop(); - encoder.release(); - - muxer.stop(); - muxer.release(); - } - - long getCurrentTimeStamp() { - return NumSamples * 1000 * 1000 / info.sampleRate; - } - - void end() { - int inputIndex = encoder.dequeueInputBuffer(-1); - if (inputIndex >= 0) { - ByteBuffer input = encoder.getInputBuffer(inputIndex); - input.clear(); - encoder.queueInputBuffer(inputIndex, 0, 0, getCurrentTimeStamp(), MediaCodec.BUFFER_FLAG_END_OF_STREAM); - } - } - - public EncoderInfo getInfo() { - return info; - } - -} \ No newline at end of file +} diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java new file mode 100755 index 0000000..6170510 --- /dev/null +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java @@ -0,0 +1,99 @@ +package com.github.axet.audiorecorder.encoders; + +import android.annotation.TargetApi; +import android.media.MediaCodec; +import android.media.MediaCodecInfo; +import android.media.MediaFormat; +import android.media.MediaMuxer; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; + +@TargetApi(21) +public class MuxerMP4 implements Encoder { + EncoderInfo info; + MediaCodec encoder; + MediaMuxer muxer; + int audioTrackIndex; + long NumSamples; + + public void create(EncoderInfo info, MediaFormat format, File out) { + this.info = info; + + try { + encoder = MediaCodec.createEncoderByType(format.getString(MediaFormat.KEY_MIME)); + encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); + encoder.start(); + + muxer = new MediaMuxer(out.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void encode(short[] buf) { + int len = buf.length * 2; + int inputIndex = encoder.dequeueInputBuffer(-1); + if (inputIndex >= 0) { + ByteBuffer input = encoder.getInputBuffer(inputIndex); + input.clear(); + for (int i = 0; i < buf.length; i++) + input.putShort(buf[i]); + encoder.queueInputBuffer(inputIndex, 0, len, getCurrentTimeStamp(), 0); + } + + NumSamples += buf.length / info.channels; + + encode(); + } + + void encode() { + MediaCodec.BufferInfo outputInfo = new MediaCodec.BufferInfo(); + int outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0); + if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { + audioTrackIndex = muxer.addTrack(encoder.getOutputFormat()); + muxer.start(); + } + + while (outputIndex >= 0) { + ByteBuffer output = encoder.getOutputBuffer(outputIndex); + output.position(outputInfo.offset); + output.limit(outputInfo.offset + outputInfo.size); + + muxer.writeSampleData(audioTrackIndex, output, outputInfo); + + encoder.releaseOutputBuffer(outputIndex, false); + outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0); + } + } + + public void close() { + end(); + encode(); + + encoder.stop(); + encoder.release(); + + muxer.stop(); + muxer.release(); + } + + long getCurrentTimeStamp() { + return NumSamples * 1000 * 1000 / info.sampleRate; + } + + void end() { + int inputIndex = encoder.dequeueInputBuffer(-1); + if (inputIndex >= 0) { + ByteBuffer input = encoder.getInputBuffer(inputIndex); + input.clear(); + encoder.queueInputBuffer(inputIndex, 0, 0, getCurrentTimeStamp(), MediaCodec.BUFFER_FLAG_END_OF_STREAM); + } + } + + public EncoderInfo getInfo() { + return info; + } + +} \ No newline at end of file From f916ac159825ac793f34f73690b664559777eb96 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 13 Mar 2016 13:44:31 +0300 Subject: [PATCH 2/3] codec re arrange --- .../activities/MainActivity.java | 9 ++++ .../activities/RecordingActivity.java | 42 +++++++++------- .../axet/audiorecorder/app/Storage.java | 12 +++-- .../audiorecorder/encoders/FileEncoder.java | 10 +++- .../audiorecorder/encoders/Format3GP.java | 29 ++++++++--- .../audiorecorder/encoders/FormatM4A.java | 2 +- .../audiorecorder/encoders/FormatWAV.java | 3 -- .../axet/audiorecorder/encoders/MuxerMP4.java | 48 ++++++++++++++----- 8 files changed, 107 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java index 1450d48..a63f30a 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/MainActivity.java @@ -52,6 +52,8 @@ import java.util.Map; import java.util.TreeMap; public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener { + public final static String TAG = MainActivity.class.getSimpleName(); + static final int TYPE_COLLAPSED = 0; static final int TYPE_EXPANDED = 1; static final int TYPE_DELETED = 2; @@ -104,6 +106,8 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr mp.release(); duration.put(f, d); add(f); + } else { + Log.e(TAG, f.toString()); } } } @@ -170,6 +174,7 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + playerStop(); dialog.cancel(); RemoveItemAnimation.apply(list, base, new Runnable() { @Override @@ -271,6 +276,10 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr void playerPlay(View v, File f) { player = MediaPlayer.create(getContext(), Uri.fromFile(f)); + if (player == null) { + Toast.makeText(MainActivity.this, "File not found", Toast.LENGTH_SHORT).show(); + return; + } player.start(); updatePlayer(v, f); diff --git a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java index 649d6de..427534b 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java +++ b/app/src/main/java/com/github/axet/audiorecorder/activities/RecordingActivity.java @@ -38,6 +38,7 @@ import com.github.axet.audiorecorder.app.Storage; import com.github.axet.audiorecorder.encoders.Encoder; import com.github.axet.audiorecorder.encoders.EncoderInfo; import com.github.axet.audiorecorder.encoders.FileEncoder; +import com.github.axet.audiorecorder.encoders.Format3GP; import com.github.axet.audiorecorder.encoders.FormatM4A; import com.github.axet.audiorecorder.encoders.FormatWAV; import com.github.axet.audiorecorder.widgets.PitchView; @@ -175,7 +176,7 @@ public class RecordingActivity extends AppCompatActivity { updateBufferSize(false); - updateSamples(0); + updateSamples(getSamples(storage.getTempRecording().length())); View cancel = findViewById(R.id.recording_cancel); cancel.setOnClickListener(new View.OnClickListener() { @@ -220,10 +221,6 @@ public class RecordingActivity extends AppCompatActivity { }); } }); - - if (permitted()) { - record(); - } } boolean isEmulator() { @@ -244,6 +241,14 @@ public class RecordingActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); + + // start once + if (thread == null) { + if (permitted()) { + record(); + } + } + Log.d(TAG, "onResume"); updateBufferSize(false); pitch.resume(); @@ -355,18 +360,7 @@ public class RecordingActivity extends AppCompatActivity { AudioRecord recorder = null; try { File tmp = storage.getTempRecording(); - - { - long ss = tmp.length(); - if (AUDIO_FORMAT == AudioFormat.ENCODING_PCM_16BIT) { - ss = ss / 2; - } - if (CHANNEL_CONFIG == AudioFormat.CHANNEL_IN_STEREO) { - ss = ss / 2; - } - - samplesTime = ss; - } + samplesTime = getSamples(tmp.length()); os = new DataOutputStream(new BufferedOutputStream(storage.open(tmp))); @@ -461,6 +455,16 @@ public class RecordingActivity extends AppCompatActivity { thread.start(); } + long getSamples(long len) { + if (AUDIO_FORMAT == AudioFormat.ENCODING_PCM_16BIT) { + len = len / 2; + } + if (CHANNEL_CONFIG == AudioFormat.CHANNEL_IN_STEREO) { + len = len / 2; + } + return len; + } + // calcuale buffer length dynamically, this way we can reduce thread cycles when activity in background // or phone screen is off. void updateBufferSize(boolean pause) { @@ -472,7 +476,6 @@ public class RecordingActivity extends AppCompatActivity { } bufferSize = CHANNEL_CONFIG == AudioFormat.CHANNEL_IN_MONO ? samplesUpdate : samplesUpdate * 2; - Log.d(TAG, "BufferSize: " + bufferSize); } } @@ -604,6 +607,9 @@ public class RecordingActivity extends AppCompatActivity { if (ext.equals("m4a")) { e = new FormatM4A(info, out); } + if (ext.equals("3gp")) { + e = new Format3GP(info, out); + } encoder = new FileEncoder(this, in, e); diff --git a/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java b/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java index 15b21e0..3654b19 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java +++ b/app/src/main/java/com/github/axet/audiorecorder/app/Storage.java @@ -144,11 +144,13 @@ public class Storage { return list; for (File f : ff) { - String[] ee = context.getResources().getStringArray(R.array.encodings_values); - String n = f.getName().toLowerCase(); - for (String e : ee) { - if (n.endsWith("." + e)) - list.add(f); + if (f.length() > 0) { + String[] ee = context.getResources().getStringArray(R.array.encodings_values); + String n = f.getName().toLowerCase(); + for (String e : ee) { + if (n.endsWith("." + e)) + list.add(f); + } } } diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java index 8a2f888..9d20894 100644 --- a/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/FileEncoder.java @@ -15,6 +15,8 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; public class FileEncoder { + public static final String TAG = FileEncoder.class.getSimpleName(); + Context context; Handler handler; @@ -23,8 +25,6 @@ public class FileEncoder { Thread thread; long samples; long cur; - Runnable progress; - Runnable done; Throwable t; public FileEncoder(Context context, File in, Encoder encoder) { @@ -53,6 +53,7 @@ public class FileEncoder { byte[] buf = new byte[(RecordingActivity.AUDIO_FORMAT == AudioFormat.ENCODING_PCM_16BIT ? 2 : 1) * 1000]; int len = is.read(buf); + Log.d("123", "len " + len); if (len <= 0) { handler.post(done); return; @@ -66,7 +67,12 @@ public class FileEncoder { } } } + } catch (RuntimeException e) { + Log.e(TAG, "Exception", e); + t = e; + handler.post(error); } catch (IOException e) { + Log.e(TAG, "Exception", e); t = e; handler.post(error); } finally { diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java index 29ed709..c333c8b 100755 --- a/app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/Format3GP.java @@ -1,21 +1,36 @@ package com.github.axet.audiorecorder.encoders; import android.annotation.TargetApi; +import android.media.MediaCodecList; import android.media.MediaFormat; import java.io.File; @TargetApi(21) -public class Format3GP extends ContainerMP4 { +public class Format3GP extends MuxerMP4 { public Format3GP(EncoderInfo info, File out) { - final int kBitRates[] = {6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850}; - MediaFormat format = new MediaFormat(); - format.setString(MediaFormat.KEY_MIME, "audio/amr-wb"); - format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate); - format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels); - format.setInteger(MediaFormat.KEY_BIT_RATE, 23850); // set maximum + + // for high bitrate AMR_WB + { +// final int kBitRates[] = {6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850}; + +// format.setString(MediaFormat.KEY_MIME, "audio/amr-wb"); +// format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate); +// format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels); +// format.setInteger(MediaFormat.KEY_BIT_RATE, 23850); // set maximum + } + + // for low bitrate, AMR_NB + { +// final int kBitRates[] = {4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200}; + + format.setString(MediaFormat.KEY_MIME, "audio/3gpp"); + format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate); // 8000 only supported + format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels); + format.setInteger(MediaFormat.KEY_BIT_RATE, 12200); // set maximum + } create(info, format, out); } diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java index a01e829..708224e 100755 --- a/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatM4A.java @@ -7,7 +7,7 @@ import android.media.MediaFormat; import java.io.File; @TargetApi(21) -public class FormatM4A extends ContainerMP4 { +public class FormatM4A extends MuxerMP4 { public FormatM4A(EncoderInfo info, File out) { MediaFormat format = new MediaFormat(); diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatWAV.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatWAV.java index 04bf58c..44e63ce 100755 --- a/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatWAV.java +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/FormatWAV.java @@ -16,9 +16,6 @@ public class FormatWAV implements Encoder { ByteOrder order = ByteOrder.LITTLE_ENDIAN; - public FormatWAV() { - } - public FormatWAV(EncoderInfo info, File out) { this.info = info; NumSamples = 0; diff --git a/app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java b/app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java index 6170510..52ab80d 100755 --- a/app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java +++ b/app/src/main/java/com/github/axet/audiorecorder/encoders/MuxerMP4.java @@ -5,6 +5,9 @@ import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.media.MediaMuxer; +import android.util.Log; + +import com.github.axet.audiorecorder.activities.SettingsActivity; import java.io.File; import java.io.IOException; @@ -33,39 +36,59 @@ public class MuxerMP4 implements Encoder { } public void encode(short[] buf) { - int len = buf.length * 2; - int inputIndex = encoder.dequeueInputBuffer(-1); - if (inputIndex >= 0) { + Log.d("123", "encode " + buf.length); + for (int offset = 0; offset < buf.length; ) { + int len = buf.length - offset; + + int inputIndex = encoder.dequeueInputBuffer(-1); + if (inputIndex < 0) + throw new RuntimeException("unable to open encoder input buffer"); + ByteBuffer input = encoder.getInputBuffer(inputIndex); input.clear(); - for (int i = 0; i < buf.length; i++) + + len = Math.min(len, input.limit() / 2); + + for (int i = 0; i < len; i++) input.putShort(buf[i]); - encoder.queueInputBuffer(inputIndex, 0, len, getCurrentTimeStamp(), 0); + + int bytes = len * 2; + + encoder.queueInputBuffer(inputIndex, 0, bytes, getCurrentTimeStamp(), 0); + Log.d("123", "put " + bytes); + NumSamples += len / info.channels; + offset += len; + + while (encode()) + ;// do encode() } - - NumSamples += buf.length / info.channels; - - encode(); } - void encode() { + boolean encode() { MediaCodec.BufferInfo outputInfo = new MediaCodec.BufferInfo(); int outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0); + if (outputIndex == MediaCodec.INFO_TRY_AGAIN_LATER) + return false; + if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { + Log.d("123", "output set " + encoder.getOutputFormat()); audioTrackIndex = muxer.addTrack(encoder.getOutputFormat()); muxer.start(); } - while (outputIndex >= 0) { + if (outputIndex >= 0) { ByteBuffer output = encoder.getOutputBuffer(outputIndex); output.position(outputInfo.offset); output.limit(outputInfo.offset + outputInfo.size); + Log.d("123", "get " + outputInfo.size); + muxer.writeSampleData(audioTrackIndex, output, outputInfo); encoder.releaseOutputBuffer(outputIndex, false); - outputIndex = encoder.dequeueOutputBuffer(outputInfo, 0); } + + return true; } public void close() { @@ -89,6 +112,7 @@ public class MuxerMP4 implements Encoder { ByteBuffer input = encoder.getInputBuffer(inputIndex); input.clear(); encoder.queueInputBuffer(inputIndex, 0, 0, getCurrentTimeStamp(), MediaCodec.BUFFER_FLAG_END_OF_STREAM); + Log.d("123", "set end "); } } From 1925eaa4601dde0950439a40c4bfb5175ac12d7b Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 13 Mar 2016 13:44:34 +0300 Subject: [PATCH 3/3] Bump version 1.0.8 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0aa7b0b..5a22e3c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.github.axet.audiorecorder" minSdkVersion 16 targetSdkVersion 23 - versionCode 8 - versionName "1.0.7" + versionCode 9 + versionName "1.0.8" } signingConfigs { release {