diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9ecafdf..26855dd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,6 +20,7 @@ android:label="@string/app_name" /> 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 5a7de3a..1450d48 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 @@ -7,6 +7,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.media.MediaPlayer; import android.net.Uri; import android.os.Build; @@ -46,6 +47,7 @@ import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Comparator; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -92,10 +94,7 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr clear(); duration.clear(); - File[] ff = dir.listFiles(); - - if (ff == null) - return; + List ff = storage.scan(dir); for (File f : ff) { if (f.isFile()) { @@ -122,6 +121,13 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr } } + public void close() { + if (player != null) { + player.release(); + player = null; + } + } + @Override public View getView(final int position, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(getContext()); @@ -232,7 +238,7 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr shareProvider.show(); - Log.d("123","show"); + Log.d("123", "show"); } }); @@ -499,4 +505,23 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + handler.post(new Runnable() { + @Override + public void run() { + list.smoothScrollToPosition(selected); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + recordings.close(); + } } 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 d8b69f9..b8aea26 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 @@ -66,7 +66,7 @@ public class RecordingActivity extends AppCompatActivity { FileEncoder encoder; Thread thread; - short[] buffer; + Integer bufferSize = 0; int sampleRate; int channelConfig; int audioFormat; @@ -85,16 +85,13 @@ public class RecordingActivity extends AppCompatActivity { int soundMode; - // how many samples passed - long samplesTime; - Storage storage; public class RecordingReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { - showRecordingActivity(); + // showRecordingActivity(); } if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { // do nothing. do not annoy user. he will see alarm screen on next screen on event. @@ -182,7 +179,7 @@ public class RecordingActivity extends AppCompatActivity { updateBufferSize(false); - updateSamples(); + updateSamples(0); View cancel = findViewById(R.id.recording_cancel); cancel.setOnClickListener(new View.OnClickListener() { @@ -207,7 +204,7 @@ public class RecordingActivity extends AppCompatActivity { if (thread != null) { stopRecording("pause"); } else { - if (permitted()) { + if (permitted(PERMISSIONS)) { resumeRecording(); } } @@ -218,6 +215,7 @@ public class RecordingActivity extends AppCompatActivity { done.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + stopRecording("encoding"); encoding(new Runnable() { @Override public void run() { @@ -250,6 +248,7 @@ public class RecordingActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); + Log.d(TAG, "onResume"); updateBufferSize(false); pitch.resume(); } @@ -257,6 +256,7 @@ public class RecordingActivity extends AppCompatActivity { @Override protected void onPause() { super.onPause(); + Log.d(TAG, "onPause"); updateBufferSize(true); pitch.pause(); } @@ -273,6 +273,7 @@ public class RecordingActivity extends AppCompatActivity { thread.interrupt(); thread = null; } + pitch.pause(); unsilent(); } @@ -350,6 +351,9 @@ public class RecordingActivity extends AppCompatActivity { Log.e(TAG, "Unable to set Thread Priority " + android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); } + // how many samples passed + long samplesTime; + DataOutputStream os = null; AudioRecord recorder = null; try { @@ -364,9 +368,7 @@ public class RecordingActivity extends AppCompatActivity { ss = ss / 2; } - synchronized (thread) { - samplesTime = ss; - } + samplesTime = ss; } os = new DataOutputStream(new BufferedOutputStream(storage.open(tmp))); @@ -393,43 +395,51 @@ public class RecordingActivity extends AppCompatActivity { // how many samples we need to update 'samples'. time clock. every 1000ms. int samplesTimeUpdate = 1000 / 1000 * sampleRate * (channelConfig == AudioFormat.CHANNEL_IN_MONO ? 1 : 2); + short[] buffer = null; + while (!Thread.currentThread().isInterrupted()) { - synchronized (thread) { - final int readSize = recorder.read(buffer, 0, buffer.length); - if (readSize <= 0) { - break; - } + synchronized (bufferSize) { + if (buffer == null || buffer.length != bufferSize) + buffer = new short[bufferSize]; + } - double sum = 0; - for (int i = 0; i < readSize; i++) { - try { - os.writeShort(buffer[i]); - } catch (IOException e) { - throw new RuntimeException(e); + final int readSize = recorder.read(buffer, 0, buffer.length); + if (readSize <= 0) { + break; + } + + Log.d("123", "" + readSize); + + double sum = 0; + for (int i = 0; i < readSize; i++) { + try { + os.writeShort(buffer[i]); + } catch (IOException e) { + throw new RuntimeException(e); + } + sum += buffer[i] * buffer[i]; + } + + int amplitude = (int) (Math.sqrt(sum / readSize)); + int s = channelConfig == AudioFormat.CHANNEL_IN_MONO ? readSize : readSize / 2; + + samplesUpdateCount += s; + if (samplesUpdateCount >= samplesUpdate) { + pitch.add((int) (amplitude / (float) maximumAltitude * 100) + 1); + samplesUpdateCount -= samplesUpdate; + } + + samplesTime += s; + samplesTimeCount += s; + if (samplesTimeCount > samplesTimeUpdate) { + final long m = samplesTime; + handle.post(new Runnable() { + @Override + public void run() { + updateSamples(m); } - sum += buffer[i] * buffer[i]; - } - - int amplitude = (int) (Math.sqrt(sum / readSize)); - int s = channelConfig == AudioFormat.CHANNEL_IN_MONO ? readSize : readSize / 2; - - samplesUpdateCount += s; - if (samplesUpdateCount >= samplesUpdate) { - pitch.add((int) (amplitude / (float) maximumAltitude * 100) + 1); - samplesUpdateCount -= samplesUpdate; - } - - samplesTime += s; - samplesTimeCount += s; - if (samplesTimeCount > samplesTimeUpdate) { - handle.post(new Runnable() { - @Override - public void run() { - updateSamples(); - } - }); - samplesTimeCount -= samplesTimeUpdate; - } + }); + samplesTimeCount -= samplesTimeUpdate; } } } catch (final RuntimeException e) { @@ -459,24 +469,19 @@ public class RecordingActivity extends AppCompatActivity { // calcuale buffer length dynamically, this way we can reduce thread cycles when activity in background // or phone screen is off. void updateBufferSize(boolean pause) { - Thread t = thread; - - if (t == null) { - t = new Thread(); - } - - synchronized (t) { + synchronized (bufferSize) { if (pause) { samplesUpdate = (int) (1000 * sampleRate / 1000.0); } else { samplesUpdate = (int) (pitch.getPitchTime() * sampleRate / 1000.0); } - buffer = new short[channelConfig == AudioFormat.CHANNEL_IN_MONO ? samplesUpdate : samplesUpdate * 2]; + bufferSize = channelConfig == AudioFormat.CHANNEL_IN_MONO ? samplesUpdate : samplesUpdate * 2; + Log.d(TAG, "BufferSize: " + bufferSize); } } - void updateSamples() { + void updateSamples(long samplesTime) { long ms = samplesTime / sampleRate * 1000; time.setText(MainApplication.formatDuration(ms)); @@ -588,8 +593,6 @@ public class RecordingActivity extends AppCompatActivity { } void encoding(final Runnable run) { - stopRecording("encoding"); - final File in = storage.getTempRecording(); final File out = targetFile; 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 42016e1..15b21e0 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 @@ -9,6 +9,8 @@ import android.preference.PreferenceManager; import android.support.v4.content.ContextCompat; import android.widget.Toast; +import com.github.axet.audiorecorder.R; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -16,7 +18,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; +import java.util.List; public class Storage { public static final String TMP_REC = "recorind.data"; @@ -132,6 +136,25 @@ public class Storage { return file; } + public List scan(File dir) { + ArrayList list = new ArrayList<>(); + + File[] ff = dir.listFiles(); + if (ff == null) + 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); + } + } + + return list; + } + public File getTempRecording() { return new File(context.getApplicationInfo().dataDir, TMP_REC); }