split main src and lib
1
android-audio-library/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
38
android-audio-library/build.gradle
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 9
|
||||
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'])
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
compile 'com.android.support:design:25.2.0'
|
||||
compile 'com.android.support:appcompat-v7:25.2.0'
|
||||
compile 'com.google.android.gms:play-services-appindexing:9.8.0'
|
||||
compile 'org.apache.commons:commons-math3:3.6.1'
|
||||
compile 'com.github.axet:android-library:1.9.9' //compile project(':android-library')
|
||||
compile 'com.github.axet:jebml:0.0.2' // compile project(':jebml')
|
||||
compile 'com.github.axet:vorbis:1.0.0' // compile project(':vorbis')
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile project(path: ':android-library')
|
||||
}
|
||||
17
android-audio-library/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/axet/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 *;
|
||||
#}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.github.axet.audiolibrary;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumentation test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.github.axet.audiolibrary.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
9
android-audio-library/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.axet.audiolibrary">
|
||||
|
||||
<application android:allowBackup="true" android:label="@string/app_name"
|
||||
android:supportsRtl="true">
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
package com.github.axet.audiorecorder.animations;
|
||||
package com.github.axet.audiolibrary.animations;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.animation.Transformation;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.github.axet.androidlibrary.animations.MarginAnimation;
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiolibrary.R;
|
||||
|
||||
public class RecordingAnimation extends MarginAnimation {
|
||||
ListView list;
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package com.github.axet.audiolibrary.app;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.media.AudioFormat;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import com.github.axet.androidlibrary.app.MainLibrary;
|
||||
import com.github.axet.audiolibrary.R;
|
||||
|
||||
public class MainApplication extends Application {
|
||||
public static final String PREFERENCE_STORAGE = "storage_path";
|
||||
public static final String PREFERENCE_RATE = "sample_rate";
|
||||
public static final String PREFERENCE_CALL = "call";
|
||||
public static final String PREFERENCE_SILENT = "silence";
|
||||
public static final String PREFERENCE_ENCODING = "encoding";
|
||||
public static final String PREFERENCE_LAST = "last_recording";
|
||||
public static final String PREFERENCE_THEME = "theme";
|
||||
public static final String PREFERENCE_CHANNELS = "channels";
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Context context = this;
|
||||
context.setTheme(getUserTheme());
|
||||
}
|
||||
|
||||
public int getUserTheme() {
|
||||
return getTheme(this, R.style.AppThemeLight, R.style.AppThemeDark);
|
||||
}
|
||||
|
||||
public static int getTheme(Context context, int light, int dark) {
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String theme = shared.getString(PREFERENCE_THEME, "");
|
||||
if (theme.equals("Theme_Dark")) {
|
||||
return dark;
|
||||
} else {
|
||||
return light;
|
||||
}
|
||||
}
|
||||
|
||||
public String formatFree(long free, long left) {
|
||||
String str = "";
|
||||
|
||||
long diff = left;
|
||||
|
||||
int diffSeconds = (int) (diff / 1000 % 60);
|
||||
int diffMinutes = (int) (diff / (60 * 1000) % 60);
|
||||
int diffHours = (int) (diff / (60 * 60 * 1000) % 24);
|
||||
int diffDays = (int) (diff / (24 * 60 * 60 * 1000));
|
||||
|
||||
if (diffDays > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.days, diffDays, diffDays);
|
||||
} else if (diffHours > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.hours, diffHours, diffHours);
|
||||
} else if (diffMinutes > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.minutes, diffMinutes, diffMinutes);
|
||||
} else if (diffSeconds > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.seconds, diffSeconds, diffSeconds);
|
||||
}
|
||||
|
||||
return getString(R.string.title_header, MainLibrary.formatSize(this, free), str);
|
||||
}
|
||||
|
||||
public static int getChannels(Context context) {
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
int i = Integer.parseInt(shared.getString(MainApplication.PREFERENCE_CHANNELS, "1"));
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int getMode(Context context) {
|
||||
switch (getChannels(context)) {
|
||||
case 1:
|
||||
return AudioFormat.CHANNEL_IN_MONO;
|
||||
case 2:
|
||||
return AudioFormat.CHANNEL_IN_STEREO;
|
||||
default:
|
||||
throw new RuntimeException("unknown mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
package com.github.axet.audiorecorder.app;
|
||||
package com.github.axet.audiolibrary.app;
|
||||
|
||||
import android.media.AudioFormat;
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.axet.audiorecorder.activities.RecordingActivity;
|
||||
|
||||
import org.apache.commons.math3.complex.Complex;
|
||||
import org.apache.commons.math3.transform.DftNormalization;
|
||||
import org.apache.commons.math3.transform.FastFourierTransformer;
|
||||
|
|
@ -0,0 +1,447 @@
|
|||
package com.github.axet.audiolibrary.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.github.axet.androidlibrary.animations.RemoveItemAnimation;
|
||||
import com.github.axet.androidlibrary.app.MainLibrary;
|
||||
import com.github.axet.androidlibrary.widgets.OpenFileDialog;
|
||||
import com.github.axet.androidlibrary.widgets.PopupShareActionProvider;
|
||||
import com.github.axet.audiolibrary.R;
|
||||
import com.github.axet.audiolibrary.animations.RecordingAnimation;
|
||||
import com.github.axet.audiolibrary.encoders.Factory;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class Recordings extends ArrayAdapter<File> implements AbsListView.OnScrollListener {
|
||||
public static String TAG = Recordings.class.getSimpleName();
|
||||
|
||||
static final int TYPE_COLLAPSED = 0;
|
||||
static final int TYPE_EXPANDED = 1;
|
||||
static final int TYPE_DELETED = 2;
|
||||
|
||||
public static class SortFiles implements Comparator<File> {
|
||||
@Override
|
||||
public int compare(File file, File file2) {
|
||||
if (file.isDirectory() && file2.isFile())
|
||||
return -1;
|
||||
else if (file.isFile() && file2.isDirectory())
|
||||
return 1;
|
||||
else
|
||||
return file.getPath().compareTo(file2.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
Handler handler;
|
||||
Storage storage;
|
||||
MediaPlayer player;
|
||||
Runnable updatePlayer;
|
||||
int selected = -1;
|
||||
ListView list;
|
||||
PopupShareActionProvider shareProvider;
|
||||
int scrollState;
|
||||
|
||||
Map<File, Integer> durations = new TreeMap<>();
|
||||
|
||||
public Recordings(Context context, ListView list) {
|
||||
super(context, 0);
|
||||
this.list = list;
|
||||
this.handler = new Handler();
|
||||
this.storage = new Storage(context);
|
||||
this.list.setOnScrollListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||
this.scrollState = scrollState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
}
|
||||
|
||||
public void scan(File dir) {
|
||||
setNotifyOnChange(false);
|
||||
clear();
|
||||
durations.clear();
|
||||
|
||||
List<File> ff = storage.scan(dir);
|
||||
|
||||
for (File f : ff) {
|
||||
if (f.isFile()) {
|
||||
MediaPlayer mp = null;
|
||||
try {
|
||||
mp = MediaPlayer.create(getContext(), Uri.fromFile(f));
|
||||
} catch (IllegalStateException e) {
|
||||
Log.d(TAG, f.toString(), e);
|
||||
}
|
||||
if (mp != null) {
|
||||
int d = mp.getDuration();
|
||||
mp.release();
|
||||
durations.put(f, d);
|
||||
add(f);
|
||||
} else {
|
||||
Log.e(TAG, f.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort(new SortFiles());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (player != null) {
|
||||
player.release();
|
||||
player = null;
|
||||
}
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void load() {
|
||||
scan(storage.getStoragePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
|
||||
if (convertView == null) {
|
||||
convertView = inflater.inflate(R.layout.recording, parent, false);
|
||||
convertView.setTag(-1);
|
||||
}
|
||||
|
||||
final View view = convertView;
|
||||
final View base = convertView.findViewById(R.id.recording_base);
|
||||
|
||||
if ((int) convertView.getTag() == TYPE_DELETED) {
|
||||
RemoveItemAnimation.restore(base);
|
||||
convertView.setTag(-1);
|
||||
}
|
||||
|
||||
final File f = getItem(position);
|
||||
|
||||
TextView title = (TextView) convertView.findViewById(R.id.recording_title);
|
||||
title.setText(f.getName());
|
||||
|
||||
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
TextView time = (TextView) convertView.findViewById(R.id.recording_time);
|
||||
time.setText(s.format(new Date(f.lastModified())));
|
||||
|
||||
TextView dur = (TextView) convertView.findViewById(R.id.recording_duration);
|
||||
dur.setText(MainLibrary.formatDuration(getContext(), durations.get(f)));
|
||||
|
||||
TextView size = (TextView) convertView.findViewById(R.id.recording_size);
|
||||
size.setText(MainLibrary.formatSize(getContext(), f.length()));
|
||||
|
||||
final View playerBase = convertView.findViewById(R.id.recording_player);
|
||||
playerBase.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
}
|
||||
});
|
||||
|
||||
final Runnable delete = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(R.string.delete_recording);
|
||||
builder.setMessage("...\\" + f.getName() + "\n\n" + getContext().getString(R.string.are_you_sure));
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
playerStop();
|
||||
dialog.cancel();
|
||||
RemoveItemAnimation.apply(list, base, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
f.delete();
|
||||
view.setTag(TYPE_DELETED);
|
||||
select(-1);
|
||||
load();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
};
|
||||
|
||||
final Runnable rename = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final OpenFileDialog.EditTextDialog e = new OpenFileDialog.EditTextDialog(getContext());
|
||||
e.setTitle(getContext().getString(R.string.rename_recording));
|
||||
e.setText(Storage.getNameNoExt(f));
|
||||
e.setPositiveButton(new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
String ext = Storage.getExt(f);
|
||||
String s = String.format("%s.%s", e.getText(), ext);
|
||||
File ff = new File(f.getParent(), s);
|
||||
f.renameTo(ff);
|
||||
load();
|
||||
}
|
||||
});
|
||||
e.show();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
if (selected == position) {
|
||||
RecordingAnimation.apply(list, convertView, true, scrollState == SCROLL_STATE_IDLE && (int) convertView.getTag() == TYPE_COLLAPSED);
|
||||
convertView.setTag(TYPE_EXPANDED);
|
||||
|
||||
updatePlayerText(convertView, f);
|
||||
|
||||
final View play = convertView.findViewById(R.id.recording_player_play);
|
||||
play.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (player == null) {
|
||||
playerPlay(playerBase, f);
|
||||
} else if (player.isPlaying()) {
|
||||
playerPause(playerBase, f);
|
||||
} else {
|
||||
playerPlay(playerBase, f);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final View edit = convertView.findViewById(R.id.recording_player_edit);
|
||||
edit.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
rename.run();
|
||||
}
|
||||
});
|
||||
|
||||
final View share = convertView.findViewById(R.id.recording_player_share);
|
||||
share.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
shareProvider = new PopupShareActionProvider(getContext(), share);
|
||||
|
||||
Intent emailIntent = new Intent(Intent.ACTION_SEND);
|
||||
emailIntent.setType(Factory.MP4A);
|
||||
emailIntent.putExtra(Intent.EXTRA_EMAIL, "");
|
||||
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
|
||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, f.getName());
|
||||
emailIntent.putExtra(Intent.EXTRA_TEXT, getContext().getString(R.string.shared_via, getContext().getString(R.string.app_name)));
|
||||
|
||||
shareProvider.setShareIntent(emailIntent);
|
||||
|
||||
shareProvider.show();
|
||||
}
|
||||
});
|
||||
|
||||
View trash = convertView.findViewById(R.id.recording_player_trash);
|
||||
trash.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
delete.run();
|
||||
}
|
||||
});
|
||||
|
||||
convertView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
select(-1);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
RecordingAnimation.apply(list, convertView, false, scrollState == SCROLL_STATE_IDLE && (int) convertView.getTag() == TYPE_EXPANDED);
|
||||
convertView.setTag(TYPE_COLLAPSED);
|
||||
|
||||
convertView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
select(position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
convertView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
PopupMenu popup = new PopupMenu(getContext(), v);
|
||||
MenuInflater inflater = popup.getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_context, popup.getMenu());
|
||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_delete) {
|
||||
delete.run();
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.action_rename) {
|
||||
rename.run();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popup.show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
void playerPlay(View v, File f) {
|
||||
if (player == null)
|
||||
player = MediaPlayer.create(getContext(), Uri.fromFile(f));
|
||||
if (player == null) {
|
||||
Toast.makeText(getContext(), R.string.file_not_found, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
player.start();
|
||||
|
||||
updatePlayerRun(v, f);
|
||||
}
|
||||
|
||||
void playerPause(View v, File f) {
|
||||
if (player != null) {
|
||||
player.pause();
|
||||
}
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
updatePlayerText(v, f);
|
||||
}
|
||||
|
||||
void playerStop() {
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
if (player != null) {
|
||||
player.stop();
|
||||
player.release();
|
||||
player = null;
|
||||
}
|
||||
}
|
||||
|
||||
void updatePlayerRun(final View v, final File f) {
|
||||
boolean playing = updatePlayerText(v, f);
|
||||
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
|
||||
if (!playing) {
|
||||
playerStop(); // clear player instance
|
||||
updatePlayerText(v, f); // update length
|
||||
return;
|
||||
}
|
||||
|
||||
updatePlayer = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updatePlayerRun(v, f);
|
||||
}
|
||||
};
|
||||
handler.postDelayed(updatePlayer, 200);
|
||||
}
|
||||
|
||||
boolean updatePlayerText(final View v, final File f) {
|
||||
ImageView i = (ImageView) v.findViewById(R.id.recording_player_play);
|
||||
|
||||
final boolean playing = player != null && player.isPlaying();
|
||||
|
||||
i.setImageResource(playing ? R.drawable.ic_pause_24dp : R.drawable.ic_play_arrow_black_24dp);
|
||||
|
||||
TextView start = (TextView) v.findViewById(R.id.recording_player_start);
|
||||
SeekBar bar = (SeekBar) v.findViewById(R.id.recording_player_seek);
|
||||
TextView end = (TextView) v.findViewById(R.id.recording_player_end);
|
||||
|
||||
int c = 0;
|
||||
int d = durations.get(f);
|
||||
|
||||
if (player != null) {
|
||||
c = player.getCurrentPosition();
|
||||
d = player.getDuration();
|
||||
}
|
||||
|
||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (!fromUser)
|
||||
return;
|
||||
|
||||
if (player == null)
|
||||
playerPlay(v, f);
|
||||
|
||||
if (player != null) {
|
||||
player.seekTo(progress);
|
||||
if (!player.isPlaying())
|
||||
playerPlay(v, f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
});
|
||||
|
||||
start.setText(MainLibrary.formatDuration(getContext(), c));
|
||||
bar.setMax(d);
|
||||
bar.setKeyProgressIncrement(1);
|
||||
bar.setProgress(c);
|
||||
end.setText("-" + MainLibrary.formatDuration(getContext(), d - c));
|
||||
|
||||
return playing;
|
||||
}
|
||||
|
||||
public void select(int pos) {
|
||||
selected = pos;
|
||||
notifyDataSetChanged();
|
||||
playerStop();
|
||||
}
|
||||
|
||||
public int getSelected() {
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,12 @@
|
|||
package com.github.axet.audiorecorder.app;
|
||||
package com.github.axet.audiolibrary.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioRecord;
|
||||
import android.media.AudioTrack;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Sound extends com.github.axet.androidlibrary.sound.Sound {
|
||||
|
||||
public Sound(Context context) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.app;
|
||||
package com.github.axet.audiolibrary.app;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
|
|
@ -9,8 +9,7 @@ import android.os.StatFs;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.encoders.Factory;
|
||||
import com.github.axet.audiolibrary.encoders.Factory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
public interface Encoder {
|
||||
void encode(short[] buf, int len);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
public class EncoderInfo {
|
||||
public int channels;
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioFormat;
|
||||
import android.os.Build;
|
||||
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
import com.github.axet.audiolibrary.R;
|
||||
import com.github.axet.audiolibrary.app.RawSamples;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
import com.github.axet.audiolibrary.app.RawSamples;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaCodecList;
|
||||
import android.media.MediaFormat;
|
||||
|
||||
import java.io.File;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaCodecInfo;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaCodec;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
import com.github.axet.vorbisjni.Vorbis;
|
||||
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
// based on http://soundfile.sapp.org/doc/WaveFormat/
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.encoders;
|
||||
package com.github.axet.audiolibrary.encoders;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaCodec;
|
||||
|
|
@ -1,16 +1,10 @@
|
|||
package com.github.axet.audiorecorder.widgets;
|
||||
package com.github.axet.audiolibrary.widgets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import com.github.axet.androidlibrary.widgets.ThemeUtils;
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
|
||||
public class FFTBarView extends FFTView {
|
||||
public static final String TAG = FFTBarView.class.getSimpleName();
|
||||
|
|
@ -1,17 +1,11 @@
|
|||
package com.github.axet.audiorecorder.widgets;
|
||||
package com.github.axet.audiolibrary.widgets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
import com.github.axet.audiolibrary.app.RawSamples;
|
||||
|
||||
public class FFTChartView extends FFTView {
|
||||
public static final String TAG = FFTChartView.class.getSimpleName();
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
package com.github.axet.audiorecorder.widgets;
|
||||
package com.github.axet.audiolibrary.widgets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import com.github.axet.androidlibrary.widgets.ThemeUtils;
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
|
||||
import org.apache.commons.math3.complex.Complex;
|
||||
import org.apache.commons.math3.transform.DftNormalization;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.github.axet.audiorecorder.widgets;
|
||||
package com.github.axet.audiolibrary.widgets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
|
|
@ -7,13 +7,12 @@ import android.graphics.Paint;
|
|||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.github.axet.androidlibrary.widgets.ThemeUtils;
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
import com.github.axet.audiolibrary.R;
|
||||
import com.github.axet.audiolibrary.app.RawSamples;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M8,5v14l11,-7z"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
||||
</vector>
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
android:id="@+id/notification_pause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/pause" />
|
||||
android:src="@drawable/ic_pause_black_24dp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
android:id="@+id/recording_player_play"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/play"
|
||||
android:src="@drawable/ic_play_arrow_black_24dp"
|
||||
android:tint="?attr/colorAccent" />
|
||||
|
||||
<View
|
||||
|
|
@ -145,7 +145,7 @@
|
|||
android:id="@+id/recording_player_share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/share"
|
||||
android:src="@drawable/ic_share_black_24dp"
|
||||
android:tint="?attr/colorAccent" />
|
||||
|
||||
<View
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
android:id="@+id/recording_player_trash"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/trash"
|
||||
android:src="@drawable/ic_delete_black_24dp"
|
||||
android:tint="?attr/colorAccent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
17
android-audio-library/src/main/res/values-ru/strings.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<resources>
|
||||
<string-array name="encodings_text">
|
||||
<item>.wav (по умолчанию)</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_header">%1$s свободно ~ %2$s</string>
|
||||
<string name="db">дБ</string>
|
||||
<string name="no">Нет</string>
|
||||
<string name="yes">Да</string>
|
||||
<string name="are_you_sure">Вы уверены?</string>
|
||||
<string name="delete_recording">Удалить запись</string>
|
||||
<string name="rename_recording">Переименовать запись</string>
|
||||
<string name="shared_via">"Создано с помощью: %1$s"</string>
|
||||
<string name="file_not_found">Файл не найден</string>
|
||||
<string name="rename">Переименовать</string>
|
||||
<string name="delete">Удалить</string>
|
||||
</resources>
|
||||
6
android-audio-library/src/main/res/values/attrs.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="titleColor" format="color" />
|
||||
<attr name="secondBackground" format="color" />
|
||||
<attr name="roundButton" format="reference" />
|
||||
</resources>
|
||||
8
android-audio-library/src/main/res/values/colors.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="secondBackground">#33333333</color>
|
||||
<color name="colorAccentLight">#FF4081</color>
|
||||
<color name="colorAccentDark">#a4a4a4</color>
|
||||
</resources>
|
||||
23
android-audio-library/src/main/res/values/strings.xml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<resources>
|
||||
<string name="app_name">Audio Library</string>
|
||||
|
||||
<string-array name="encodings_text">
|
||||
<item>.wav (default)</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="encodings_values" translatable="false">
|
||||
<item>wav</item>
|
||||
</string-array>
|
||||
|
||||
<string name="title_header">%1$s free ~ %2$s left</string>
|
||||
<string name="db">dB</string>
|
||||
<string name="no">No</string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="are_you_sure">"Are you sure ? "</string>
|
||||
<string name="delete_recording">Delete Recording</string>
|
||||
<string name="rename_recording">Rename Recording</string>
|
||||
<string name="shared_via">"Shared via %1$s"</string>
|
||||
<string name="file_not_found">File not found</string>
|
||||
<string name="rename">Rename</string>
|
||||
<string name="delete">Delete</string>
|
||||
</resources>
|
||||
48
android-audio-library/src/main/res/values/styles.xml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppThemeLight" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccentLight</item>
|
||||
<item name="titleColor">@color/colorPrimary</item>
|
||||
<item name="secondBackground">#c2c2c2</item>
|
||||
<item name="roundButton">@drawable/round_button_light</item>
|
||||
<item name="alertDialogTheme">@style/AppThemeDialogLight</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDialogLight" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
|
||||
<item name="colorAccent">@color/colorAccentLight</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||
<item name="android:textColorPrimary">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDark" parent="Theme.AppCompat">
|
||||
<item name="colorPrimaryDark">@color/primary_dark_material_dark</item>
|
||||
<item name="colorPrimary">@color/primary_material_dark</item>
|
||||
<item name="colorAccent">@color/colorAccentDark</item>
|
||||
<item name="titleColor">@android:color/primary_text_dark</item>
|
||||
<item name="secondBackground">#151515</item>
|
||||
<item name="roundButton">@drawable/round_button_dark</item>
|
||||
<item name="alertDialogTheme">@style/AppThemeDialogDark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDialogDark" parent="@style/Theme.AppCompat.Dialog.Alert">
|
||||
<item name="colorAccent">@color/colorAccentDark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDark.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.github.axet.audiolibrary;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -45,10 +45,5 @@ dependencies {
|
|||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:25.2.0'
|
||||
compile 'com.android.support:support-v4:25.2.0'
|
||||
compile 'com.android.support:design:25.2.0'
|
||||
compile 'com.google.android.gms:play-services-appindexing:9.8.0'
|
||||
compile 'org.apache.commons:commons-math3:3.6.1'
|
||||
compile 'com.github.axet:android-library:1.9.9' //compile project(':android-library')
|
||||
compile 'com.github.axet:jebml:0.0.2' // compile project(':jebml')
|
||||
compile 'com.github.axet:vorbis:1.0.0' // compile project(':vorbis')
|
||||
compile project(':android-audio-library')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ package com.github.axet.audiorecorder;
|
|||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
package com.github.axet.audiorecorder.activities;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
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;
|
||||
import android.os.Bundle;
|
||||
|
|
@ -18,67 +15,39 @@ import android.support.design.widget.FloatingActionButton;
|
|||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.github.axet.androidlibrary.animations.RemoveItemAnimation;
|
||||
import com.github.axet.androidlibrary.app.MainLibrary;
|
||||
import com.github.axet.androidlibrary.widgets.OpenFileDialog;
|
||||
import com.github.axet.androidlibrary.widgets.PopupShareActionProvider;
|
||||
import com.github.axet.audiolibrary.app.Recordings;
|
||||
import com.github.axet.audiolibrary.app.Storage;
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.animations.RecordingAnimation;
|
||||
import com.github.axet.audiorecorder.app.MainApplication;
|
||||
import com.github.axet.audiorecorder.app.Storage;
|
||||
import com.github.axet.audiorecorder.encoders.Factory;
|
||||
import com.google.android.gms.appindexing.Action;
|
||||
import com.google.android.gms.appindexing.AppIndex;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener {
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
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;
|
||||
|
||||
/**
|
||||
* ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||
* See https://g.co/AppIndexing/AndroidStudio for more information.
|
||||
*/
|
||||
private GoogleApiClient client;
|
||||
FloatingActionButton fab;
|
||||
Handler handler = new Handler();
|
||||
|
||||
final int[] ALL = {TYPE_COLLAPSED, TYPE_EXPANDED};
|
||||
|
||||
int scrollState;
|
||||
|
||||
ListView list;
|
||||
Recordings recordings;
|
||||
Storage storage;
|
||||
ListView list;
|
||||
Handler handler;
|
||||
PopupShareActionProvider shareProvider;
|
||||
|
||||
int themeId;
|
||||
|
||||
|
|
@ -89,381 +58,6 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
context.startActivity(i);
|
||||
}
|
||||
|
||||
static class SortFiles implements Comparator<File> {
|
||||
@Override
|
||||
public int compare(File file, File file2) {
|
||||
if (file.isDirectory() && file2.isFile())
|
||||
return -1;
|
||||
else if (file.isFile() && file2.isDirectory())
|
||||
return 1;
|
||||
else
|
||||
return file.getPath().compareTo(file2.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
public class Recordings extends ArrayAdapter<File> {
|
||||
MediaPlayer player;
|
||||
Runnable updatePlayer;
|
||||
int selected = -1;
|
||||
|
||||
Map<File, Integer> durations = new TreeMap<>();
|
||||
|
||||
public Recordings(Context context) {
|
||||
super(context, 0);
|
||||
}
|
||||
|
||||
public void scan(File dir) {
|
||||
setNotifyOnChange(false);
|
||||
clear();
|
||||
durations.clear();
|
||||
|
||||
List<File> ff = storage.scan(dir);
|
||||
|
||||
for (File f : ff) {
|
||||
if (f.isFile()) {
|
||||
MediaPlayer mp = null;
|
||||
try {
|
||||
mp = MediaPlayer.create(getContext(), Uri.fromFile(f));
|
||||
} catch (IllegalStateException e) {
|
||||
Log.d(TAG, f.toString(), e);
|
||||
}
|
||||
if (mp != null) {
|
||||
int d = mp.getDuration();
|
||||
mp.release();
|
||||
durations.put(f, d);
|
||||
add(f);
|
||||
} else {
|
||||
Log.e(TAG, f.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort(new SortFiles());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (player != null) {
|
||||
player.release();
|
||||
player = null;
|
||||
}
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
|
||||
if (convertView == null) {
|
||||
convertView = inflater.inflate(R.layout.recording, parent, false);
|
||||
convertView.setTag(-1);
|
||||
}
|
||||
|
||||
final View view = convertView;
|
||||
final View base = convertView.findViewById(R.id.recording_base);
|
||||
|
||||
if ((int) convertView.getTag() == TYPE_DELETED) {
|
||||
RemoveItemAnimation.restore(base);
|
||||
convertView.setTag(-1);
|
||||
}
|
||||
|
||||
final File f = getItem(position);
|
||||
|
||||
TextView title = (TextView) convertView.findViewById(R.id.recording_title);
|
||||
title.setText(f.getName());
|
||||
|
||||
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
TextView time = (TextView) convertView.findViewById(R.id.recording_time);
|
||||
time.setText(s.format(new Date(f.lastModified())));
|
||||
|
||||
TextView dur = (TextView) convertView.findViewById(R.id.recording_duration);
|
||||
dur.setText(MainLibrary.formatDuration(getContext(), durations.get(f)));
|
||||
|
||||
TextView size = (TextView) convertView.findViewById(R.id.recording_size);
|
||||
size.setText(MainLibrary.formatSize(getContext(), f.length()));
|
||||
|
||||
final View playerBase = convertView.findViewById(R.id.recording_player);
|
||||
playerBase.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
}
|
||||
});
|
||||
|
||||
final Runnable delete = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(R.string.delete_recording);
|
||||
builder.setMessage("...\\" + f.getName() + "\n\n" + getString(R.string.are_you_sure));
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
playerStop();
|
||||
dialog.cancel();
|
||||
RemoveItemAnimation.apply(list, base, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
f.delete();
|
||||
view.setTag(TYPE_DELETED);
|
||||
select(-1);
|
||||
load();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
};
|
||||
|
||||
final Runnable rename = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final OpenFileDialog.EditTextDialog e = new OpenFileDialog.EditTextDialog(getContext());
|
||||
e.setTitle(getString(R.string.rename_recording));
|
||||
e.setText(Storage.getNameNoExt(f));
|
||||
e.setPositiveButton(new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
String ext = Storage.getExt(f);
|
||||
String s = String.format("%s.%s", e.getText(), ext);
|
||||
File ff = new File(f.getParent(), s);
|
||||
f.renameTo(ff);
|
||||
load();
|
||||
}
|
||||
});
|
||||
e.show();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
if (selected == position) {
|
||||
RecordingAnimation.apply(list, convertView, true, scrollState == SCROLL_STATE_IDLE && (int) convertView.getTag() == TYPE_COLLAPSED);
|
||||
convertView.setTag(TYPE_EXPANDED);
|
||||
|
||||
updatePlayerText(convertView, f);
|
||||
|
||||
final View play = convertView.findViewById(R.id.recording_player_play);
|
||||
play.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (player == null) {
|
||||
playerPlay(playerBase, f);
|
||||
} else if (player.isPlaying()) {
|
||||
playerPause(playerBase, f);
|
||||
} else {
|
||||
playerPlay(playerBase, f);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final View edit = convertView.findViewById(R.id.recording_player_edit);
|
||||
edit.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
rename.run();
|
||||
}
|
||||
});
|
||||
|
||||
final View share = convertView.findViewById(R.id.recording_player_share);
|
||||
share.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
shareProvider = new PopupShareActionProvider(getContext(), share);
|
||||
|
||||
Intent emailIntent = new Intent(Intent.ACTION_SEND);
|
||||
emailIntent.setType(Factory.MP4A);
|
||||
emailIntent.putExtra(Intent.EXTRA_EMAIL, "");
|
||||
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
|
||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, f.getName());
|
||||
emailIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.shared_via, getString(R.string.app_name)));
|
||||
|
||||
shareProvider.setShareIntent(emailIntent);
|
||||
|
||||
shareProvider.show();
|
||||
}
|
||||
});
|
||||
|
||||
View trash = convertView.findViewById(R.id.recording_player_trash);
|
||||
trash.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
delete.run();
|
||||
}
|
||||
});
|
||||
|
||||
convertView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
select(-1);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
RecordingAnimation.apply(list, convertView, false, scrollState == SCROLL_STATE_IDLE && (int) convertView.getTag() == TYPE_EXPANDED);
|
||||
convertView.setTag(TYPE_COLLAPSED);
|
||||
|
||||
convertView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
select(position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
convertView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
PopupMenu popup = new PopupMenu(getContext(), v);
|
||||
MenuInflater inflater = popup.getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_context, popup.getMenu());
|
||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_delete) {
|
||||
delete.run();
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.action_rename) {
|
||||
rename.run();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popup.show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
void playerPlay(View v, File f) {
|
||||
if (player == null)
|
||||
player = MediaPlayer.create(getContext(), Uri.fromFile(f));
|
||||
if (player == null) {
|
||||
Toast.makeText(MainActivity.this, R.string.file_not_found, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
player.start();
|
||||
|
||||
updatePlayerRun(v, f);
|
||||
}
|
||||
|
||||
void playerPause(View v, File f) {
|
||||
if (player != null) {
|
||||
player.pause();
|
||||
}
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
updatePlayerText(v, f);
|
||||
}
|
||||
|
||||
void playerStop() {
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
if (player != null) {
|
||||
player.stop();
|
||||
player.release();
|
||||
player = null;
|
||||
}
|
||||
}
|
||||
|
||||
void updatePlayerRun(final View v, final File f) {
|
||||
boolean playing = updatePlayerText(v, f);
|
||||
|
||||
if (updatePlayer != null) {
|
||||
handler.removeCallbacks(updatePlayer);
|
||||
updatePlayer = null;
|
||||
}
|
||||
|
||||
if (!playing) {
|
||||
playerStop(); // clear player instance
|
||||
updatePlayerText(v, f); // update length
|
||||
return;
|
||||
}
|
||||
|
||||
updatePlayer = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updatePlayerRun(v, f);
|
||||
}
|
||||
};
|
||||
handler.postDelayed(updatePlayer, 200);
|
||||
}
|
||||
|
||||
boolean updatePlayerText(final View v, final File f) {
|
||||
ImageView i = (ImageView) v.findViewById(R.id.recording_player_play);
|
||||
|
||||
final boolean playing = player != null && player.isPlaying();
|
||||
|
||||
i.setImageResource(playing ? R.drawable.pause : R.drawable.play);
|
||||
|
||||
TextView start = (TextView) v.findViewById(R.id.recording_player_start);
|
||||
SeekBar bar = (SeekBar) v.findViewById(R.id.recording_player_seek);
|
||||
TextView end = (TextView) v.findViewById(R.id.recording_player_end);
|
||||
|
||||
int c = 0;
|
||||
int d = durations.get(f);
|
||||
|
||||
if (player != null) {
|
||||
c = player.getCurrentPosition();
|
||||
d = player.getDuration();
|
||||
}
|
||||
|
||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (!fromUser)
|
||||
return;
|
||||
|
||||
if (player == null)
|
||||
playerPlay(v, f);
|
||||
|
||||
if (player != null) {
|
||||
player.seekTo(progress);
|
||||
if (!player.isPlaying())
|
||||
playerPlay(v, f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
});
|
||||
|
||||
start.setText(MainLibrary.formatDuration(getContext(), c));
|
||||
bar.setMax(d);
|
||||
bar.setKeyProgressIncrement(1);
|
||||
bar.setProgress(c);
|
||||
end.setText("-" + MainLibrary.formatDuration(getContext(), d - c));
|
||||
|
||||
return playing;
|
||||
}
|
||||
|
||||
public void select(int pos) {
|
||||
selected = pos;
|
||||
notifyDataSetChanged();
|
||||
playerStop();
|
||||
}
|
||||
}
|
||||
|
||||
public void setAppTheme(int id) {
|
||||
super.setTheme(id);
|
||||
themeId = id;
|
||||
|
|
@ -480,25 +74,19 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
storage = new Storage(this);
|
||||
|
||||
// ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||
// See https://g.co/AppIndexing/AndroidStudio for more information.
|
||||
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
|
||||
|
||||
storage = new Storage(this);
|
||||
handler = new Handler();
|
||||
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
// if (Build.VERSION.SDK_INT >= 16)
|
||||
// toolbar.setBackground(new ColorDrawable(MainApplication.getActionbarColor(this)));
|
||||
// else
|
||||
// toolbar.setBackgroundDrawable(new ColorDrawable(MainApplication.getActionbarColor(this)));
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
fab = (FloatingActionButton) findViewById(R.id.fab);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
fab.setClickable(false);
|
||||
recordings.select(-1);
|
||||
RecordingActivity.startActivity(MainActivity.this, false);
|
||||
// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
|
|
@ -506,10 +94,8 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
}
|
||||
});
|
||||
|
||||
recordings = new Recordings(this);
|
||||
|
||||
list = (ListView) findViewById(R.id.list);
|
||||
list.setOnScrollListener(this);
|
||||
recordings = new Recordings(this, list);
|
||||
list.setAdapter(recordings);
|
||||
list.setEmptyView(findViewById(R.id.empty_list));
|
||||
|
||||
|
|
@ -525,11 +111,6 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
}
|
||||
}
|
||||
|
||||
// load recordings
|
||||
void load() {
|
||||
recordings.scan(storage.getStoragePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
|
@ -578,16 +159,14 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
}
|
||||
|
||||
if (permitted(PERMISSIONS))
|
||||
load();
|
||||
recordings.load();
|
||||
else
|
||||
load();
|
||||
recordings.load();
|
||||
|
||||
checkPending();
|
||||
|
||||
updateHeader();
|
||||
|
||||
fab.setClickable(true);
|
||||
|
||||
final int selected = getLastRecording();
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
|
|
@ -631,7 +210,7 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
case 1:
|
||||
if (permitted(permissions)) {
|
||||
storage.migrateLocalStorage();
|
||||
load();
|
||||
recordings.load();
|
||||
checkPending();
|
||||
} else {
|
||||
Toast.makeText(this, R.string.not_permitted, Toast.LENGTH_SHORT).show();
|
||||
|
|
@ -666,15 +245,6 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||
this.scrollState = scrollState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
|
@ -682,7 +252,7 @@ public class MainActivity extends AppCompatActivity implements AbsListView.OnScr
|
|||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
list.smoothScrollToPosition(recordings.selected);
|
||||
list.smoothScrollToPosition(recordings.getSelected());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,15 +38,15 @@ import com.github.axet.androidlibrary.animations.MarginBottomAnimation;
|
|||
import com.github.axet.androidlibrary.app.MainLibrary;
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.app.MainApplication;
|
||||
import com.github.axet.audiorecorder.app.RawSamples;
|
||||
import com.github.axet.audiorecorder.app.Sound;
|
||||
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.Factory;
|
||||
import com.github.axet.audiorecorder.encoders.FileEncoder;
|
||||
import com.github.axet.audiolibrary.app.RawSamples;
|
||||
import com.github.axet.audiolibrary.app.Sound;
|
||||
import com.github.axet.audiolibrary.app.Storage;
|
||||
import com.github.axet.audiolibrary.encoders.Encoder;
|
||||
import com.github.axet.audiolibrary.encoders.EncoderInfo;
|
||||
import com.github.axet.audiolibrary.encoders.Factory;
|
||||
import com.github.axet.audiolibrary.encoders.FileEncoder;
|
||||
import com.github.axet.audiorecorder.services.RecordingService;
|
||||
import com.github.axet.audiorecorder.widgets.PitchView;
|
||||
import com.github.axet.audiolibrary.widgets.PitchView;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
|
@ -439,7 +439,7 @@ public class RecordingActivity extends AppCompatActivity {
|
|||
final ImageView playButton = (ImageView) box.findViewById(R.id.recording_play);
|
||||
|
||||
if (show) {
|
||||
playButton.setImageResource(R.drawable.pause);
|
||||
playButton.setImageResource(R.drawable.ic_pause_24dp);
|
||||
|
||||
playIndex = editSample;
|
||||
|
||||
|
|
@ -478,7 +478,7 @@ public class RecordingActivity extends AppCompatActivity {
|
|||
play = null;
|
||||
}
|
||||
pitch.play(-1);
|
||||
playButton.setImageResource(R.drawable.play);
|
||||
playButton.setImageResource(R.drawable.ic_play_arrow_black_24dp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import android.widget.Toast;
|
|||
|
||||
import com.github.axet.audiorecorder.R;
|
||||
import com.github.axet.audiorecorder.app.MainApplication;
|
||||
import com.github.axet.audiorecorder.encoders.Factory;
|
||||
import com.github.axet.audiolibrary.encoders.Factory;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
|
|
|
|||
|
|
@ -10,83 +10,12 @@ import com.github.axet.androidlibrary.app.MainLibrary;
|
|||
import com.github.axet.androidlibrary.widgets.ThemeUtils;
|
||||
import com.github.axet.audiorecorder.R;
|
||||
|
||||
public class MainApplication extends Application {
|
||||
public static final String PREFERENCE_STORAGE = "storage_path";
|
||||
public static final String PREFERENCE_RATE = "sample_rate";
|
||||
public static final String PREFERENCE_CALL = "call";
|
||||
public static final String PREFERENCE_SILENT = "silence";
|
||||
public static final String PREFERENCE_ENCODING = "encoding";
|
||||
public static final String PREFERENCE_LAST = "last_recording";
|
||||
public static final String PREFERENCE_THEME = "theme";
|
||||
public static final String PREFERENCE_CHANNELS = "channels";
|
||||
public class MainApplication extends com.github.axet.audiolibrary.app.MainApplication {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
PreferenceManager.setDefaultValues(this, R.xml.pref_general, false);
|
||||
|
||||
Context context = this;
|
||||
context.setTheme(getUserTheme());
|
||||
}
|
||||
|
||||
public static int getTheme(Context context, int light, int dark) {
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String theme = shared.getString(PREFERENCE_THEME, "");
|
||||
if (theme.equals("Theme_Dark")) {
|
||||
return dark;
|
||||
} else {
|
||||
return light;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getActionbarColor(Context context) {
|
||||
int colorId = MainApplication.getTheme(context, R.attr.colorPrimary, R.attr.secondBackground);
|
||||
int color = ThemeUtils.getThemeColor(context, colorId);
|
||||
return color;
|
||||
}
|
||||
|
||||
public int getUserTheme() {
|
||||
return getTheme(this, R.style.AppThemeLight, R.style.AppThemeDark);
|
||||
}
|
||||
|
||||
public String formatFree(long free, long left) {
|
||||
String str = "";
|
||||
|
||||
long diff = left;
|
||||
|
||||
int diffSeconds = (int) (diff / 1000 % 60);
|
||||
int diffMinutes = (int) (diff / (60 * 1000) % 60);
|
||||
int diffHours = (int) (diff / (60 * 60 * 1000) % 24);
|
||||
int diffDays = (int) (diff / (24 * 60 * 60 * 1000));
|
||||
|
||||
if (diffDays > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.days, diffDays, diffDays);
|
||||
} else if (diffHours > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.hours, diffHours, diffHours);
|
||||
} else if (diffMinutes > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.minutes, diffMinutes, diffMinutes);
|
||||
} else if (diffSeconds > 0) {
|
||||
str = getResources().getQuantityString(R.plurals.seconds, diffSeconds, diffSeconds);
|
||||
}
|
||||
|
||||
return getString(R.string.title_header, MainLibrary.formatSize(this, free), str);
|
||||
}
|
||||
|
||||
public static int getChannels(Context context) {
|
||||
final SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
int i = Integer.parseInt(shared.getString(MainApplication.PREFERENCE_CHANNELS, "1"));
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int getMode(Context context) {
|
||||
switch (getChannels(context)) {
|
||||
case 1:
|
||||
return AudioFormat.CHANNEL_IN_MONO;
|
||||
case 2:
|
||||
return AudioFormat.CHANNEL_IN_STEREO;
|
||||
default:
|
||||
throw new RuntimeException("unknown mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ public class RecordingService extends Service {
|
|||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.d(TAG, "onCreate");
|
||||
|
||||
receiver = new RecordingReceiver();
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_SCREEN_ON);
|
||||
|
|
@ -142,7 +141,7 @@ public class RecordingService extends Service {
|
|||
view.setOnClickPendingIntent(R.id.status_bar_latest_event_content, main);
|
||||
view.setTextViewText(R.id.notification_text, ".../" + targetFile);
|
||||
view.setOnClickPendingIntent(R.id.notification_pause, pe);
|
||||
view.setImageViewResource(R.id.notification_pause, !recording ? R.drawable.play : R.drawable.pause);
|
||||
view.setImageViewResource(R.id.notification_pause, !recording ? R.drawable.ic_play_arrow_black_24dp : R.drawable.ic_pause_24dp);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
|
||||
.setOngoing(true)
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 149 B |
|
Before Width: | Height: | Size: 441 B |
|
Before Width: | Height: | Size: 513 B |
|
Before Width: | Height: | Size: 127 B |
|
Before Width: | Height: | Size: 295 B |
|
Before Width: | Height: | Size: 349 B |
|
Before Width: | Height: | Size: 164 B |
|
Before Width: | Height: | Size: 552 B |
|
Before Width: | Height: | Size: 624 B |
|
Before Width: | Height: | Size: 226 B |
|
Before Width: | Height: | Size: 893 B |
|
Before Width: | Height: | Size: 976 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<com.github.axet.audiorecorder.widgets.PitchView
|
||||
<com.github.axet.audiolibrary.widgets.PitchView
|
||||
android:id="@+id/recording_pitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:background="?attr/roundButton"
|
||||
android:src="@drawable/play" />
|
||||
android:src="@drawable/ic_play_arrow_black_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/recording_edit_done"
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@
|
|||
<item>8 kHz (телефон)</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="encodings_text">
|
||||
<item>.wav (по умолчанию)</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="channels_text">
|
||||
<item>Моно (по умолчанию)</item>
|
||||
<item>Стерео</item>
|
||||
|
|
@ -28,13 +24,6 @@
|
|||
<string name="action_settings">Настройки</string>
|
||||
<string name="not_permitted">Доступ запрещен</string>
|
||||
<string name="no_folder_app">Программа для просмотра папок не установлена</string>
|
||||
<string name="file_not_found">Файл не найден</string>
|
||||
<string name="shared_via">"Создано с помощью: %1$s"</string>
|
||||
<string name="rename_recording">Переименовать запись</string>
|
||||
<string name="no">Нет</string>
|
||||
<string name="yes">Да</string>
|
||||
<string name="are_you_sure">Вы уверены?</string>
|
||||
<string name="delete_recording">Удалить запись</string>
|
||||
<string name="hold_by_call">пауза (звонок)</string>
|
||||
<string name="encoding">кодировка</string>
|
||||
<string name="pause">пауза</string>
|
||||
|
|
@ -44,10 +33,6 @@
|
|||
<string name="recording">запись</string>
|
||||
<string name="encoding_title">Кодирование...</string>
|
||||
<string name="recording_title">Запись</string>
|
||||
<string name="db">дБ</string>
|
||||
<string name="title_header">%1$s свободно ~ %2$s</string>
|
||||
<string name="rename">Переименовать</string>
|
||||
<string name="delete">Удалить</string>
|
||||
<string name="open_recording_folder">Открыть папку с записями</string>
|
||||
<string name="recording_list_is_empty">Список записей пуст.\n\nНажмите на \'Микрофон\' чтобы начать запись.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="titleColor" format="color" />
|
||||
<attr name="secondBackground" format="color" />
|
||||
<attr name="roundButton" format="reference" />
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="secondBackground">#33333333</color>
|
||||
<color name="colorAccentLight">#FF4081</color>
|
||||
<color name="colorAccentDark">#a4a4a4</color>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -21,14 +21,6 @@
|
|||
<item>8000</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="encodings_text">
|
||||
<item>.wav (default)</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="encodings_values" translatable="false">
|
||||
<item>wav</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="themes_text">
|
||||
<item>Theme White (default)</item>
|
||||
<item>Theme Dark</item>
|
||||
|
|
@ -52,13 +44,6 @@
|
|||
<string name="action_settings">Settings</string>
|
||||
<string name="not_permitted">Not permitted</string>
|
||||
<string name="no_folder_app">No folder view application installed</string>
|
||||
<string name="file_not_found">File not found</string>
|
||||
<string name="shared_via">"Shared via %1$s"</string>
|
||||
<string name="rename_recording">Rename Recording</string>
|
||||
<string name="no">No</string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="are_you_sure">"Are you sure ? "</string>
|
||||
<string name="delete_recording">Delete Recording</string>
|
||||
<string name="hold_by_call">pause (hold by call)</string>
|
||||
<string name="encoding">encoding</string>
|
||||
<string name="pause">pause</string>
|
||||
|
|
@ -68,10 +53,6 @@
|
|||
<string name="recording">recording</string>
|
||||
<string name="encoding_title">Encoding...</string>
|
||||
<string name="recording_title">Recording</string>
|
||||
<string name="title_header">%1$s free ~ %2$s left</string>
|
||||
<string name="db">dB</string>
|
||||
<string name="rename">Rename</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="open_recording_folder">Open Recording Folder</string>
|
||||
<string name="recording_list_is_empty">Recording List is Empty\n\nClick Record to Start Recording</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,48 +1,2 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppThemeLight" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccentLight</item>
|
||||
<item name="titleColor">@color/colorPrimary</item>
|
||||
<item name="secondBackground">#c2c2c2</item>
|
||||
<item name="roundButton">@drawable/round_button_light</item>
|
||||
<item name="alertDialogTheme">@style/AppThemeDialogLight</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDialogLight" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
|
||||
<item name="colorAccent">@color/colorAccentLight</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||
<item name="android:textColorPrimary">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDark" parent="Theme.AppCompat">
|
||||
<item name="colorPrimaryDark">@color/primary_dark_material_dark</item>
|
||||
<item name="colorPrimary">@color/primary_material_dark</item>
|
||||
<item name="colorAccent">@color/colorAccentDark</item>
|
||||
<item name="titleColor">@android:color/primary_text_dark</item>
|
||||
<item name="secondBackground">#151515</item>
|
||||
<item name="roundButton">@drawable/round_button_dark</item>
|
||||
<item name="alertDialogTheme">@style/AppThemeDialogDark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDialogDark" parent="@style/Theme.AppCompat.Dialog.Alert">
|
||||
<item name="colorAccent">@color/colorAccentDark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDark.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
include ':app', ':android-library', ':jebml'
|
||||
include ':app', ':android-library', ':jebml', ':android-audio-library'
|
||||