我正在使用 Un4seen Bass Lib,但出现此错误
I am using Un4seen Bass Lib and I am getting this Error
谁能帮我解决这个错误。我的应用程序 运行 正常,但是当单击 activity 按钮时,它崩溃并出现此错误 logcat。无论如何,我的 .so 文件在 jniLibs 文件夹中。
12-26 12:02:12.393 22612-22612/com.project.voicechanger
E/AndroidRuntime: FATAL EXCEPTION: main Process:
com.project.voicechanger, PID: 22612 java.lang.UnsatisfiedLinkError:
dalvik.system.PathClassLoader[DexPathList[[zip file
"/data/app/com.project.voicechanger-2/base.apk"],nativeLibraryDirectories=[/data/app/com.prject.voicechanger-2/lib/arm64,
/data/app/com.project.voicechanger-2/base.apk!/lib/arm64-v8a,
/vendor/lib64, /system/lib64]]] couldn't find "libbass.so"
at java.lang.Runtime.loadLibrary(Runtime.java:367)
at java.lang.System.loadLibrary(System.java:1076)
at com.un4seen.bass.BASS.(BASS.java:695)
at com.ypyproductions.voicechanger.EffectActivity.onInitAudioDevice(EffectActivity.java:384)
at com.ypyproductions.voicechanger.EffectActivity.setupInfo(EffectActivity.java:119)
at com.ypyproductions.voicechanger.EffectActivity.onCreate(EffectActivity.java:100)
at android.app.Activity.performCreate(Activity.java:6323)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
at android.app.ActivityThread.access0(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1347)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这是EffectActivity.java上出现的错误:
package com.ypyproductions.voicechanger;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.un4seen.bass.BASS;
import com.ypyproductions.materialdialogs.MaterialDialog;
import com.ypyproductions.voicechanger.adapter.EffectAdapter;
import com.ypyproductions.voicechanger.basseffect.DBMediaPlayer;
import com.ypyproductions.voicechanger.basseffect.IDBMediaListener;
import com.ypyproductions.voicechanger.dataMng.JsonParsingUtils;
import com.ypyproductions.voicechanger.dataMng.TotalDataManager;
import com.ypyproductions.voicechanger.object.EffectObject;
import com.ypyproductions.voicechanger.soundMng.SoundManager;
import com.ypyproductions.voicechanger.task.DBTask;
import com.ypyproductions.voicechanger.task.IDBCallback;
import com.ypyproductions.voicechanger.task.IDBTaskListener;
import com.ypyproductions.voicechanger.utils.ApplicationUtils;
import com.ypyproductions.voicechanger.utils.DBLog;
import com.ypyproductions.voicechanger.utils.DirectionUtils;
import com.ypyproductions.voicechanger.utils.IOUtils;
import com.ypyproductions.voicechanger.utils.StringUtils;
import java.io.File;
import java.util.ArrayList;
/**
*
*
* @author:YPY Productions
* @Skype: baopfiev_k50
* @Mobile : +84 983 028 786
* @Email: dotrungbao@gmail.com
* @Website: www.ypyproductions.com
* @Project:TemplateChangeTheme
* @Date:Aug 4, 2015
*
*/
public class EffectActivity extends DBFragmentActivity implements OnClickListener, EffectAdapter.OnEffectListener {
public static final String TAG = EffectActivity.class.getSimpleName();
private ListView mListViewEffects;
private ArrayList<EffectObject> mListEffectObjects;
private EffectAdapter mEffectApdater;
private String mPathAudio;
private TextView mTvHeader;
private boolean isInit;
private DBMediaPlayer mDBMedia;
private String mNameExportVoice;
private AdView adView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_effects);
Intent mIntent = getIntent();
if (mIntent != null) {
mPathAudio = mIntent.getStringExtra(KEY_PATH_AUDIO);
}
mListViewEffects = (ListView) findViewById(R.id.list_effects);
mTvHeader = (TextView) findViewById(R.id.tv_header);
mTvHeader.setTypeface(mTypefaceLogo);
setUpBlurLayout();
setupLayoutAdmob();
if (!StringUtils.isEmptyString(mPathAudio)) {
File mFile = new File(mPathAudio);
if (mFile.exists() && mFile.isFile()) {
setupInfo();
}
else {
showToast("File not found exception");
backToHome();
}
}
else {
backToHome();
}
}
private void setupInfo(){
mListEffectObjects = TotalDataManager.getInstance().getListEffectObjects();
if (mListEffectObjects != null && mListEffectObjects.size() > 0) {
mEffectApdater = new EffectAdapter(this, mListEffectObjects, mTypefaceAvenir);
mEffectApdater.setOnEffectListener(this);
mListViewEffects.setAdapter(mEffectApdater);
onInitAudioDevice();
createDBMedia();
}
else{
startLoad(new IDBCallback() {
@Override
public void onAction() {
setupInfo();
}
});
}
}
private void startLoad(final IDBCallback mCallback){
DBTask mDBTask = new DBTask(new IDBTaskListener() {
public ArrayList<EffectObject> mListEffects;
@Override
public void onPreExcute() {
showProgressDialog();
}
@Override
public void onDoInBackground() {
String data = IOUtils.readStringFromAssets(EffectActivity.this, "effects.dat");
mListEffects = JsonParsingUtils.parsingListEffectObject(data);
DBLog.d(TAG, "===============>Size=" + mListEffects.size());
if (mListEffects != null && mListEffects.size() > 0) {
mTotalMng.setListEffectObjects(mListEffects);
}
}
@Override
public void onPostExcute() {
dimissProgressDialog();
if (mListEffects == null || mListEffects.size() == 0) {
backToHome();
return;
}
if(mCallback!=null){
mCallback.onAction();
}
}
});
mDBTask.execute();
}
private void setupLayoutAdmob() {
boolean b=SHOW_ADVERTISEMENT;
RelativeLayout layout = (RelativeLayout) findViewById(R.id.layout_ad);
if (ApplicationUtils.isOnline(this) && b) {
adView = new AdView(this);
adView.setAdUnitId(ADMOB_ID_BANNER);
adView.setAdSize(AdSize.SMART_BANNER);
layout.addView(adView);
AdRequest mAdRequest = new AdRequest.Builder().addTestDevice("51F0A3F4C13F05DD49DE0D71F2B369FB").build();
adView.loadAd(mAdRequest);
return;
}
layout.setVisibility(View.GONE);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_back:
mSoundMng.play(this, R.raw.click);
backToHome();
break;
case R.id.btn_gallery:
mSoundMng.play(this, R.raw.click);
deleteMainFile();
onDestroyMedia();
Intent mIntent = new Intent(this, GalleryActivity.class);
DirectionUtils.changeActivity(this, R.anim.slide_in_from_right, R.anim.slide_out_to_left, true, mIntent);
break;
default:
break;
}
}
private void deleteMainFile() {
if (!StringUtils.isEmptyString(mPathAudio)) {
try {
File file = new File(mPathAudio);
file.delete();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
protected void onDestroy() {
if (adView != null) {
adView.destroy();
}
super.onDestroy();
}
private void onDestroyMedia(){
try{
if (mDBMedia != null) {
mDBMedia.releaseAudio();
}
BASS.BASS_PluginFree(0);
BASS.BASS_Free();
TotalDataManager.getInstance().onResetState();
}
catch(Exception e){
e.printStackTrace();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
backToHome();
return true;
}
return super.onKeyDown(keyCode, event);
}
private void backToHome() {
deleteMainFile();
onDestroyMedia();
Intent mIntent = new Intent(this, RecordActivity.class);
DirectionUtils.changeActivity(this, R.anim.slide_in_from_left, R.anim.slide_out_to_right, true, mIntent);
}
@Override
public void onPlayEffect(EffectObject mEffectObject) {
boolean isPlaying = mEffectObject.isPlaying();
if (isPlaying) {
mEffectObject.setPlaying(false);
if (mDBMedia != null) {
mDBMedia.pauseAudio();
}
}
else {
TotalDataManager.getInstance().onResetState();
mEffectObject.setPlaying(true);
if (mDBMedia != null) {
mDBMedia.setReverse(mEffectObject.isReverse());
mDBMedia.setAudioPitch(mEffectObject.getPitch());
mDBMedia.setAudioRate(mEffectObject.getRate());
mDBMedia.setAudioReverb(mEffectObject.getReverb());
mDBMedia.setAudioEQ(mEffectObject.getEq());
mDBMedia.setFlangerEffect(mEffectObject.isFlanger());
mDBMedia.setAudioEcho(mEffectObject.isEcho());
if (mDBMedia.isPlaying()) {
if(!mEffectObject.isReverse()){
mDBMedia.seekTo(0);
}
else{
mDBMedia.seekTo(mDBMedia.getDuration());
}
}
mDBMedia.startAudio();
}
}
mEffectApdater.notifyDataSetChanged();
}
@Override
protected void onPause() {
super.onPause();
if (mDBMedia != null) {
resetStateAudio();
}
}
@Override
public void onShareEffect(final EffectObject mEffectObject) {
if(mDBMedia!=null){
resetStateAudio();
}
SoundManager.getInstance().play(this, R.raw.click);
mNameExportVoice=String.format(FORMAT_NAME_VOICE, String.valueOf(System.currentTimeMillis()/1000));
showDialogEnterName(new IDBCallback() {
@Override
public void onAction() {
if (mDBMedia != null) {
startSaveEffect(mEffectObject, new IDBCallback() {
@Override
public void onAction() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile.exists() && mOutPutFile.isFile()) {
String mInfoSave = String.format(getString(R.string.info_save_voice), mOutPutFile.getAbsolutePath());
showToast(mInfoSave);
showDiaglogShare(mEffectObject);
}
}
});
}
}
});
}
private void resetStateAudio() {
TotalDataManager.getInstance().onResetState();
if (mEffectApdater != null) {
mEffectApdater.notifyDataSetChanged();
}
if (mDBMedia!=null && mDBMedia.isPlaying()) {
mDBMedia.pauseAudio();
}
}
private void startSaveEffect(final EffectObject mEffectObject, final IDBCallback mDBCallback) {
File file = new File(mPathAudio);
final File mDir = file.getParentFile();
final File mTempOutPutFile = new File(mDir, mNameExportVoice);
final DBMediaPlayer mDBExportMedia = new DBMediaPlayer(mPathAudio);
DBTask mDBTask = new DBTask(new IDBTaskListener() {
@Override
public void onPreExcute() {
showProgressDialog();
}
@Override
public void onDoInBackground() {
if (mDBExportMedia != null) {
boolean b = mDBExportMedia.initMediaToSave();
if (b) {
mDBExportMedia.setReverse(mEffectObject.isReverse());
mDBExportMedia.setAudioPitch(mEffectObject.getPitch());
mDBExportMedia.setAudioRate(mEffectObject.getRate());
mDBExportMedia.setAudioReverb(mEffectObject.getReverb());
mDBExportMedia.setFlangerEffect(mEffectObject.isFlanger());
mDBExportMedia.setAudioEcho(mEffectObject.isEcho());
mDBExportMedia.setAudioEQ(mEffectObject.getEq());
mDBExportMedia.saveToFile(mTempOutPutFile.getAbsolutePath());
mDBExportMedia.releaseAudio();
}
}
}
@Override
public void onPostExcute() {
dimissProgressDialog();
if (mDBCallback != null) {
mDBCallback.onAction();
}
}
});
mDBTask.execute();
}
public void onInitAudioDevice() {
if (!isInit) {
isInit = true;
if (!BASS.BASS_Init(-1, 44100, 0)) {
new Exception(TAG + " Can't initialize device").printStackTrace();
this.isInit = false;
return;
}
String libpath = getApplicationInfo().nativeLibraryDir;
try{
BASS.BASS_PluginLoad(libpath + "/libbass_fx.so", 0);
BASS.BASS_PluginLoad(libpath + "/libbassenc.so", 0);
BASS.BASS_PluginLoad(libpath + "/libbassmix.so", 0);
BASS.BASS_PluginLoad(libpath + "/libbasswv.so", 0);
}
catch(Exception e){
e.printStackTrace();
}
}
}
private void createDBMedia() {
if (!StringUtils.isEmptyString(mPathAudio)) {
mDBMedia = new DBMediaPlayer(mPathAudio);
mDBMedia.prepareAudio();
mDBMedia.setOnDBMediaListener(new IDBMediaListener() {
@Override
public void onMediaError() {
}
@Override
public void onMediaCompletion() {
TotalDataManager.getInstance().onResetState();
mEffectApdater.notifyDataSetChanged();
}
});
}
}
private void showDiaglogShare(final EffectObject mEffectObject) {
MaterialDialog.Builder mBuilder = new MaterialDialog.Builder(this);
mBuilder.backgroundColor(getResources().getColor(R.color.white));
mBuilder.title(R.string.title_options);
mBuilder.titleColor(getResources().getColor(R.color.black_text));
mBuilder.items(R.array.list_options);
mBuilder.contentColor(getResources().getColor(R.color.black_text));
mBuilder.positiveColor(getResources().getColor(R.color.pink));
mBuilder.negativeColor(getResources().getColor(R.color.black_secondary_text));
mBuilder.positiveText(R.string.title_cancel);
mBuilder.autoDismiss(true);
mBuilder.typeface(mTypefaceBold, mTypefaceLight);
mBuilder.itemsCallback(new MaterialDialog.ListCallback() {
@Override
public void onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
if (which == 0) {
shareFile();
}
else if (which == 1) {
saveAsRingtone();
}
else if (which == 2) {
saveAsNotification();
}
}
});
mBuilder.build().show();
}
private void shareFile() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile.exists() && mOutPutFile.isFile()) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
if(mNameExportVoice.endsWith(AUDIO_RECORDER_FILE_EXT_MP3)){
shareIntent.setType("audio/mp3");
}
else{
shareIntent.setType("audio/*");
}
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(mOutPutFile));
startActivity(Intent.createChooser(shareIntent, "Share Via"));
}
}
private void saveAsRingtone() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile != null && mOutPutFile.isFile()) {
Uri mUri=null;
ContentValues values = new ContentValues();
values.put(MediaColumns.DATA, mOutPutFile.getAbsolutePath());
values.put(MediaColumns.TITLE, mNameExportVoice.replaceAll(AUDIO_RECORDER_FILE_EXT_WAV, ""));
values.put(MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
String id=getIdFromContentUri(mOutPutFile.getAbsolutePath());
if(StringUtils.isEmptyString(id)){
mUri = this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(mOutPutFile.getAbsolutePath()), values);
}
else{
this.getContentResolver().update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
, values, MediaColumns._ID+" = ?", new String[]{id});
mUri=Uri.parse(String.format(FORMAT_URI, id));
}
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, mUri);
showToast(R.string.info_set_ringtone_successfully);
}
}
private void saveAsNotification() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile != null && mOutPutFile.isFile()) {
Uri mUri=null;
ContentValues values = new ContentValues();
values.put(MediaColumns.DATA, mOutPutFile.getAbsolutePath());
values.put(MediaColumns.TITLE, mNameExportVoice.replaceAll(AUDIO_RECORDER_FILE_EXT_WAV, ""));
values.put(MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
String id=getIdFromContentUri(mOutPutFile.getAbsolutePath());
if(StringUtils.isEmptyString(id)){
mUri = this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(mOutPutFile.getAbsolutePath()), values);
}
else{
this.getContentResolver().update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
, values, MediaColumns._ID+" = ?", new String[]{id});
mUri=Uri.parse(String.format(FORMAT_URI, id));
}
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION, mUri);
showToast(R.string.info_set_notification_successfully);
}
}
private String getIdFromContentUri(String path) {
try {
if(path!=null){
String id;
String[] filePathColumn = {MediaColumns._ID};
String[] selectionArgs = {path};
Cursor cursor = this.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
filePathColumn, MediaColumns.DATA+" = ?", selectionArgs, null);
if(cursor!=null && cursor.moveToFirst()){
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
id = cursor.getString(columnIndex);
cursor.close();
return id;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void showDialogEnterName(final IDBCallback mDCallback) {
final EditText mEdName = new EditText(this);
mEdName.setSingleLine(true);
Builder builder = new Builder(this).setTitle(getString(R.string.title_enter_name)).setView(mEdName)
.setPositiveButton(getString(R.string.title_ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ApplicationUtils.hiddenVirtualKeyboard(EffectActivity.this, mEdName);
String mNewName = mEdName.getText().toString();
if(!StringUtils.isEmptyString(mNewName)){
if(StringUtils.isContainsSpecialCharacter(mNewName)){
showToast(R.string.info_your_name_error);
return;
}
mNameExportVoice=mNewName+".wav";
}
if(mDCallback!=null){
mDCallback.onAction();
}
}
}).setNegativeButton(getString(R.string.title_skip), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(mDCallback!=null){
mDCallback.onAction();
}
}
});
AlertDialog mDialogEnterPass = builder.create();
mDialogEnterPass.show();
}
}
这是应用 gradle 文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '28.0.3'
dexOptions {
javaMaxHeapSize "4g"
}
defaultConfig {
applicationId "com.ypyproductions.voicechanger"
minSdkVersion 15
targetSdkVersion 27
versionCode 20181
versionName "1.0"
multiDexEnabled true
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':nineOldLibrary')
implementation project(':materialDialog')
implementation 'com.android.support:support-fragment:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:support-media-compat:27.1.1'
implementation 'com.android.support:support-compat:27.1.1'
implementation 'com.android.support:customtabs:27.1.1'
implementation 'com.android.support:multidex:1.0.3'
implementation 'com.google.android.gms:play-services-ads:17.1.2'
implementation 'com.google.android.gms:play-services-identity:16.0.0'
implementation 'com.google.android.gms:play-services-gcm:16.0.0'
}
我正在使用 Android Studio 和 Windows 10 笔记本电脑。
来自 un4seen.com 论坛:
1 mkdir lib, then, copy armeabi to lib, the tree should bee lib/armeeabi/libbass.so
2 zip lib directory: $zip -r libbass.zip lib
3 rename: $mv libbass.zip libbass.jar
4 copy libbass.jar to YourProject/Youproject/src/main/libs, "YourProject/Youproject/src/main/" includes AndroidManifests.xml, res, java, libs
5 add this line:
compile fileTree(dir: 'libs', include: '*.jar')
to your build.gradle---->dependencies
谁能帮我解决这个错误。我的应用程序 运行 正常,但是当单击 activity 按钮时,它崩溃并出现此错误 logcat。无论如何,我的 .so 文件在 jniLibs 文件夹中。
12-26 12:02:12.393 22612-22612/com.project.voicechanger E/AndroidRuntime: FATAL EXCEPTION: main Process: com.project.voicechanger, PID: 22612 java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.project.voicechanger-2/base.apk"],nativeLibraryDirectories=[/data/app/com.prject.voicechanger-2/lib/arm64, /data/app/com.project.voicechanger-2/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libbass.so" at java.lang.Runtime.loadLibrary(Runtime.java:367) at java.lang.System.loadLibrary(System.java:1076) at com.un4seen.bass.BASS.(BASS.java:695) at com.ypyproductions.voicechanger.EffectActivity.onInitAudioDevice(EffectActivity.java:384) at com.ypyproductions.voicechanger.EffectActivity.setupInfo(EffectActivity.java:119) at com.ypyproductions.voicechanger.EffectActivity.onCreate(EffectActivity.java:100) at android.app.Activity.performCreate(Activity.java:6323) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) at android.app.ActivityThread.access0(ActivityThread.java:153) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1347) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5451) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这是EffectActivity.java上出现的错误:
package com.ypyproductions.voicechanger;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.un4seen.bass.BASS;
import com.ypyproductions.materialdialogs.MaterialDialog;
import com.ypyproductions.voicechanger.adapter.EffectAdapter;
import com.ypyproductions.voicechanger.basseffect.DBMediaPlayer;
import com.ypyproductions.voicechanger.basseffect.IDBMediaListener;
import com.ypyproductions.voicechanger.dataMng.JsonParsingUtils;
import com.ypyproductions.voicechanger.dataMng.TotalDataManager;
import com.ypyproductions.voicechanger.object.EffectObject;
import com.ypyproductions.voicechanger.soundMng.SoundManager;
import com.ypyproductions.voicechanger.task.DBTask;
import com.ypyproductions.voicechanger.task.IDBCallback;
import com.ypyproductions.voicechanger.task.IDBTaskListener;
import com.ypyproductions.voicechanger.utils.ApplicationUtils;
import com.ypyproductions.voicechanger.utils.DBLog;
import com.ypyproductions.voicechanger.utils.DirectionUtils;
import com.ypyproductions.voicechanger.utils.IOUtils;
import com.ypyproductions.voicechanger.utils.StringUtils;
import java.io.File;
import java.util.ArrayList;
/**
*
*
* @author:YPY Productions
* @Skype: baopfiev_k50
* @Mobile : +84 983 028 786
* @Email: dotrungbao@gmail.com
* @Website: www.ypyproductions.com
* @Project:TemplateChangeTheme
* @Date:Aug 4, 2015
*
*/
public class EffectActivity extends DBFragmentActivity implements OnClickListener, EffectAdapter.OnEffectListener {
public static final String TAG = EffectActivity.class.getSimpleName();
private ListView mListViewEffects;
private ArrayList<EffectObject> mListEffectObjects;
private EffectAdapter mEffectApdater;
private String mPathAudio;
private TextView mTvHeader;
private boolean isInit;
private DBMediaPlayer mDBMedia;
private String mNameExportVoice;
private AdView adView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_effects);
Intent mIntent = getIntent();
if (mIntent != null) {
mPathAudio = mIntent.getStringExtra(KEY_PATH_AUDIO);
}
mListViewEffects = (ListView) findViewById(R.id.list_effects);
mTvHeader = (TextView) findViewById(R.id.tv_header);
mTvHeader.setTypeface(mTypefaceLogo);
setUpBlurLayout();
setupLayoutAdmob();
if (!StringUtils.isEmptyString(mPathAudio)) {
File mFile = new File(mPathAudio);
if (mFile.exists() && mFile.isFile()) {
setupInfo();
}
else {
showToast("File not found exception");
backToHome();
}
}
else {
backToHome();
}
}
private void setupInfo(){
mListEffectObjects = TotalDataManager.getInstance().getListEffectObjects();
if (mListEffectObjects != null && mListEffectObjects.size() > 0) {
mEffectApdater = new EffectAdapter(this, mListEffectObjects, mTypefaceAvenir);
mEffectApdater.setOnEffectListener(this);
mListViewEffects.setAdapter(mEffectApdater);
onInitAudioDevice();
createDBMedia();
}
else{
startLoad(new IDBCallback() {
@Override
public void onAction() {
setupInfo();
}
});
}
}
private void startLoad(final IDBCallback mCallback){
DBTask mDBTask = new DBTask(new IDBTaskListener() {
public ArrayList<EffectObject> mListEffects;
@Override
public void onPreExcute() {
showProgressDialog();
}
@Override
public void onDoInBackground() {
String data = IOUtils.readStringFromAssets(EffectActivity.this, "effects.dat");
mListEffects = JsonParsingUtils.parsingListEffectObject(data);
DBLog.d(TAG, "===============>Size=" + mListEffects.size());
if (mListEffects != null && mListEffects.size() > 0) {
mTotalMng.setListEffectObjects(mListEffects);
}
}
@Override
public void onPostExcute() {
dimissProgressDialog();
if (mListEffects == null || mListEffects.size() == 0) {
backToHome();
return;
}
if(mCallback!=null){
mCallback.onAction();
}
}
});
mDBTask.execute();
}
private void setupLayoutAdmob() {
boolean b=SHOW_ADVERTISEMENT;
RelativeLayout layout = (RelativeLayout) findViewById(R.id.layout_ad);
if (ApplicationUtils.isOnline(this) && b) {
adView = new AdView(this);
adView.setAdUnitId(ADMOB_ID_BANNER);
adView.setAdSize(AdSize.SMART_BANNER);
layout.addView(adView);
AdRequest mAdRequest = new AdRequest.Builder().addTestDevice("51F0A3F4C13F05DD49DE0D71F2B369FB").build();
adView.loadAd(mAdRequest);
return;
}
layout.setVisibility(View.GONE);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_back:
mSoundMng.play(this, R.raw.click);
backToHome();
break;
case R.id.btn_gallery:
mSoundMng.play(this, R.raw.click);
deleteMainFile();
onDestroyMedia();
Intent mIntent = new Intent(this, GalleryActivity.class);
DirectionUtils.changeActivity(this, R.anim.slide_in_from_right, R.anim.slide_out_to_left, true, mIntent);
break;
default:
break;
}
}
private void deleteMainFile() {
if (!StringUtils.isEmptyString(mPathAudio)) {
try {
File file = new File(mPathAudio);
file.delete();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
protected void onDestroy() {
if (adView != null) {
adView.destroy();
}
super.onDestroy();
}
private void onDestroyMedia(){
try{
if (mDBMedia != null) {
mDBMedia.releaseAudio();
}
BASS.BASS_PluginFree(0);
BASS.BASS_Free();
TotalDataManager.getInstance().onResetState();
}
catch(Exception e){
e.printStackTrace();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
backToHome();
return true;
}
return super.onKeyDown(keyCode, event);
}
private void backToHome() {
deleteMainFile();
onDestroyMedia();
Intent mIntent = new Intent(this, RecordActivity.class);
DirectionUtils.changeActivity(this, R.anim.slide_in_from_left, R.anim.slide_out_to_right, true, mIntent);
}
@Override
public void onPlayEffect(EffectObject mEffectObject) {
boolean isPlaying = mEffectObject.isPlaying();
if (isPlaying) {
mEffectObject.setPlaying(false);
if (mDBMedia != null) {
mDBMedia.pauseAudio();
}
}
else {
TotalDataManager.getInstance().onResetState();
mEffectObject.setPlaying(true);
if (mDBMedia != null) {
mDBMedia.setReverse(mEffectObject.isReverse());
mDBMedia.setAudioPitch(mEffectObject.getPitch());
mDBMedia.setAudioRate(mEffectObject.getRate());
mDBMedia.setAudioReverb(mEffectObject.getReverb());
mDBMedia.setAudioEQ(mEffectObject.getEq());
mDBMedia.setFlangerEffect(mEffectObject.isFlanger());
mDBMedia.setAudioEcho(mEffectObject.isEcho());
if (mDBMedia.isPlaying()) {
if(!mEffectObject.isReverse()){
mDBMedia.seekTo(0);
}
else{
mDBMedia.seekTo(mDBMedia.getDuration());
}
}
mDBMedia.startAudio();
}
}
mEffectApdater.notifyDataSetChanged();
}
@Override
protected void onPause() {
super.onPause();
if (mDBMedia != null) {
resetStateAudio();
}
}
@Override
public void onShareEffect(final EffectObject mEffectObject) {
if(mDBMedia!=null){
resetStateAudio();
}
SoundManager.getInstance().play(this, R.raw.click);
mNameExportVoice=String.format(FORMAT_NAME_VOICE, String.valueOf(System.currentTimeMillis()/1000));
showDialogEnterName(new IDBCallback() {
@Override
public void onAction() {
if (mDBMedia != null) {
startSaveEffect(mEffectObject, new IDBCallback() {
@Override
public void onAction() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile.exists() && mOutPutFile.isFile()) {
String mInfoSave = String.format(getString(R.string.info_save_voice), mOutPutFile.getAbsolutePath());
showToast(mInfoSave);
showDiaglogShare(mEffectObject);
}
}
});
}
}
});
}
private void resetStateAudio() {
TotalDataManager.getInstance().onResetState();
if (mEffectApdater != null) {
mEffectApdater.notifyDataSetChanged();
}
if (mDBMedia!=null && mDBMedia.isPlaying()) {
mDBMedia.pauseAudio();
}
}
private void startSaveEffect(final EffectObject mEffectObject, final IDBCallback mDBCallback) {
File file = new File(mPathAudio);
final File mDir = file.getParentFile();
final File mTempOutPutFile = new File(mDir, mNameExportVoice);
final DBMediaPlayer mDBExportMedia = new DBMediaPlayer(mPathAudio);
DBTask mDBTask = new DBTask(new IDBTaskListener() {
@Override
public void onPreExcute() {
showProgressDialog();
}
@Override
public void onDoInBackground() {
if (mDBExportMedia != null) {
boolean b = mDBExportMedia.initMediaToSave();
if (b) {
mDBExportMedia.setReverse(mEffectObject.isReverse());
mDBExportMedia.setAudioPitch(mEffectObject.getPitch());
mDBExportMedia.setAudioRate(mEffectObject.getRate());
mDBExportMedia.setAudioReverb(mEffectObject.getReverb());
mDBExportMedia.setFlangerEffect(mEffectObject.isFlanger());
mDBExportMedia.setAudioEcho(mEffectObject.isEcho());
mDBExportMedia.setAudioEQ(mEffectObject.getEq());
mDBExportMedia.saveToFile(mTempOutPutFile.getAbsolutePath());
mDBExportMedia.releaseAudio();
}
}
}
@Override
public void onPostExcute() {
dimissProgressDialog();
if (mDBCallback != null) {
mDBCallback.onAction();
}
}
});
mDBTask.execute();
}
public void onInitAudioDevice() {
if (!isInit) {
isInit = true;
if (!BASS.BASS_Init(-1, 44100, 0)) {
new Exception(TAG + " Can't initialize device").printStackTrace();
this.isInit = false;
return;
}
String libpath = getApplicationInfo().nativeLibraryDir;
try{
BASS.BASS_PluginLoad(libpath + "/libbass_fx.so", 0);
BASS.BASS_PluginLoad(libpath + "/libbassenc.so", 0);
BASS.BASS_PluginLoad(libpath + "/libbassmix.so", 0);
BASS.BASS_PluginLoad(libpath + "/libbasswv.so", 0);
}
catch(Exception e){
e.printStackTrace();
}
}
}
private void createDBMedia() {
if (!StringUtils.isEmptyString(mPathAudio)) {
mDBMedia = new DBMediaPlayer(mPathAudio);
mDBMedia.prepareAudio();
mDBMedia.setOnDBMediaListener(new IDBMediaListener() {
@Override
public void onMediaError() {
}
@Override
public void onMediaCompletion() {
TotalDataManager.getInstance().onResetState();
mEffectApdater.notifyDataSetChanged();
}
});
}
}
private void showDiaglogShare(final EffectObject mEffectObject) {
MaterialDialog.Builder mBuilder = new MaterialDialog.Builder(this);
mBuilder.backgroundColor(getResources().getColor(R.color.white));
mBuilder.title(R.string.title_options);
mBuilder.titleColor(getResources().getColor(R.color.black_text));
mBuilder.items(R.array.list_options);
mBuilder.contentColor(getResources().getColor(R.color.black_text));
mBuilder.positiveColor(getResources().getColor(R.color.pink));
mBuilder.negativeColor(getResources().getColor(R.color.black_secondary_text));
mBuilder.positiveText(R.string.title_cancel);
mBuilder.autoDismiss(true);
mBuilder.typeface(mTypefaceBold, mTypefaceLight);
mBuilder.itemsCallback(new MaterialDialog.ListCallback() {
@Override
public void onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
if (which == 0) {
shareFile();
}
else if (which == 1) {
saveAsRingtone();
}
else if (which == 2) {
saveAsNotification();
}
}
});
mBuilder.build().show();
}
private void shareFile() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile.exists() && mOutPutFile.isFile()) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
if(mNameExportVoice.endsWith(AUDIO_RECORDER_FILE_EXT_MP3)){
shareIntent.setType("audio/mp3");
}
else{
shareIntent.setType("audio/*");
}
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(mOutPutFile));
startActivity(Intent.createChooser(shareIntent, "Share Via"));
}
}
private void saveAsRingtone() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile != null && mOutPutFile.isFile()) {
Uri mUri=null;
ContentValues values = new ContentValues();
values.put(MediaColumns.DATA, mOutPutFile.getAbsolutePath());
values.put(MediaColumns.TITLE, mNameExportVoice.replaceAll(AUDIO_RECORDER_FILE_EXT_WAV, ""));
values.put(MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
String id=getIdFromContentUri(mOutPutFile.getAbsolutePath());
if(StringUtils.isEmptyString(id)){
mUri = this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(mOutPutFile.getAbsolutePath()), values);
}
else{
this.getContentResolver().update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
, values, MediaColumns._ID+" = ?", new String[]{id});
mUri=Uri.parse(String.format(FORMAT_URI, id));
}
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, mUri);
showToast(R.string.info_set_ringtone_successfully);
}
}
private void saveAsNotification() {
File file = new File(mPathAudio);
File mDir = file.getParentFile();
final File mOutPutFile = new File(mDir, mNameExportVoice);
if (mOutPutFile != null && mOutPutFile.isFile()) {
Uri mUri=null;
ContentValues values = new ContentValues();
values.put(MediaColumns.DATA, mOutPutFile.getAbsolutePath());
values.put(MediaColumns.TITLE, mNameExportVoice.replaceAll(AUDIO_RECORDER_FILE_EXT_WAV, ""));
values.put(MediaColumns.MIME_TYPE, "audio/*");
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
String id=getIdFromContentUri(mOutPutFile.getAbsolutePath());
if(StringUtils.isEmptyString(id)){
mUri = this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(mOutPutFile.getAbsolutePath()), values);
}
else{
this.getContentResolver().update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
, values, MediaColumns._ID+" = ?", new String[]{id});
mUri=Uri.parse(String.format(FORMAT_URI, id));
}
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION, mUri);
showToast(R.string.info_set_notification_successfully);
}
}
private String getIdFromContentUri(String path) {
try {
if(path!=null){
String id;
String[] filePathColumn = {MediaColumns._ID};
String[] selectionArgs = {path};
Cursor cursor = this.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
filePathColumn, MediaColumns.DATA+" = ?", selectionArgs, null);
if(cursor!=null && cursor.moveToFirst()){
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
id = cursor.getString(columnIndex);
cursor.close();
return id;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void showDialogEnterName(final IDBCallback mDCallback) {
final EditText mEdName = new EditText(this);
mEdName.setSingleLine(true);
Builder builder = new Builder(this).setTitle(getString(R.string.title_enter_name)).setView(mEdName)
.setPositiveButton(getString(R.string.title_ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ApplicationUtils.hiddenVirtualKeyboard(EffectActivity.this, mEdName);
String mNewName = mEdName.getText().toString();
if(!StringUtils.isEmptyString(mNewName)){
if(StringUtils.isContainsSpecialCharacter(mNewName)){
showToast(R.string.info_your_name_error);
return;
}
mNameExportVoice=mNewName+".wav";
}
if(mDCallback!=null){
mDCallback.onAction();
}
}
}).setNegativeButton(getString(R.string.title_skip), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(mDCallback!=null){
mDCallback.onAction();
}
}
});
AlertDialog mDialogEnterPass = builder.create();
mDialogEnterPass.show();
}
}
这是应用 gradle 文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '28.0.3'
dexOptions {
javaMaxHeapSize "4g"
}
defaultConfig {
applicationId "com.ypyproductions.voicechanger"
minSdkVersion 15
targetSdkVersion 27
versionCode 20181
versionName "1.0"
multiDexEnabled true
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':nineOldLibrary')
implementation project(':materialDialog')
implementation 'com.android.support:support-fragment:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:support-media-compat:27.1.1'
implementation 'com.android.support:support-compat:27.1.1'
implementation 'com.android.support:customtabs:27.1.1'
implementation 'com.android.support:multidex:1.0.3'
implementation 'com.google.android.gms:play-services-ads:17.1.2'
implementation 'com.google.android.gms:play-services-identity:16.0.0'
implementation 'com.google.android.gms:play-services-gcm:16.0.0'
}
我正在使用 Android Studio 和 Windows 10 笔记本电脑。
来自 un4seen.com 论坛:
1 mkdir lib, then, copy armeabi to lib, the tree should bee lib/armeeabi/libbass.so
2 zip lib directory: $zip -r libbass.zip lib
3 rename: $mv libbass.zip libbass.jar
4 copy libbass.jar to YourProject/Youproject/src/main/libs, "YourProject/Youproject/src/main/" includes AndroidManifests.xml, res, java, libs
5 add this line:
compile fileTree(dir: 'libs', include: '*.jar')
to your build.gradle---->dependencies