Can anyone help me with this error. My app is running properly but when clicking activity button, it crashes and this error logcat appears. Anyway, my .so files are in jniLibs folder.
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.access$900(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)
This is the EffectActivity.java appeared on the error:
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();
}
}
This is the app gradle file:
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'
}
I am using Android Studio and Windows 10 laptop.
From un4seen.com forum:
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