خطای null pointer exeption در کار با mediaPlayer (حل شد)
سلام
من توی برنامم از یک ارایه ی یک بعدی از مدیا پلیر استفاده میکنم و مطمن هستم که درست مقدار دهی میکنم
ولی توی بعضی دستگاه ها به خطای null pointer میرسم (روی امولاتور 4.2.2 مشکلی نیس ولی روی گوشی خودم اندروید 2.3.3 کرش میکنه)
شکل تعریف من اینجوریه:
public class G extends Application {
public static MediaPlayer[] soundPlayer = new MediaPlayer[8];
public static final int SOUND_BUBBLE_UP = 0;
public static final int SOUND_BUBBLE_DOWN = 1;
public static final int SOUND_BUBBLE_SHAKE = 2;
public static final int SOUND_BUBBLE_CLICK = 3;
public static final int SOUND_BUBBLE_PRIZE = 4;
public static final int SOUND_GAME_WIN = 5;
public static final int SOUND_GAME_STRESS = 6;
public static final int SOUND_FIRE_END = 7;
@Override
public void onCreate() {
soundPlayer[G.SOUND_BUBBLE_UP] = MediaPlayer.create(G.this, R.raw.bubble_up);
soundPlayer[G.SOUND_BUBBLE_DOWN] = MediaPlayer.create(G.this, R.raw.bubble_down);
soundPlayer[G.SOUND_BUBBLE_SHAKE] = MediaPlayer.create(G.this, R.raw.bubble_shake);
soundPlayer[G.SOUND_BUBBLE_CLICK] = MediaPlayer.create(G.this, R.raw.bubble_click);
soundPlayer[G.SOUND_BUBBLE_PRIZE] = MediaPlayer.create(G.this, R.raw.bubble_prize);
soundPlayer[G.SOUND_GAME_WIN] = MediaPlayer.create(G.this, R.raw.game_win);
soundPlayer[G.SOUND_GAME_STRESS] = MediaPlayer.create(G.this, R.raw.game_stress);
soundPlayer[G.SOUND_FIRE_END] = MediaPlayer.create(G.this, R.raw.fire_end_game);
super.onCreate();
}
public static void playSFX(int order) {
switch (order) {
case G.SOUND_BUBBLE_UP:
if (G.soundPlayer[G.SOUND_BUBBLE_UP].isPlaying()) {
G.soundPlayer[G.SOUND_BUBBLE_UP].seekTo(0);
}
else {
G.soundPlayer[G.SOUND_BUBBLE_UP].start();
}
break;
case G.SOUND_BUBBLE_DOWN:
if (G.soundPlayer[G.SOUND_BUBBLE_DOWN].isPlaying()) {
G.soundPlayer[G.SOUND_BUBBLE_DOWN].seekTo(0);
} else {
G.soundPlayer[G.SOUND_BUBBLE_DOWN].start();
}
break;
case G.SOUND_BUBBLE_SHAKE:
if (G.soundPlayer[G.SOUND_BUBBLE_SHAKE].isPlaying()) {
G.soundPlayer[G.SOUND_BUBBLE_SHAKE].seekTo(0);
} else {
G.soundPlayer[G.SOUND_BUBBLE_SHAKE].start();
}
break;
case G.SOUND_BUBBLE_CLICK:
if (G.soundPlayer[G.SOUND_BUBBLE_CLICK].isPlaying()) {
G.soundPlayer[G.SOUND_BUBBLE_CLICK].seekTo(0);
} else {
G.soundPlayer[G.SOUND_BUBBLE_CLICK].start();
}
break;
case G.SOUND_BUBBLE_PRIZE:
if (G.soundPlayer[G.SOUND_BUBBLE_PRIZE].isPlaying()) {
G.soundPlayer[G.SOUND_BUBBLE_PRIZE].seekTo(0);
} else {
G.soundPlayer[G.SOUND_BUBBLE_PRIZE].start();
}
break;
case G.SOUND_GAME_WIN:
if (G.soundPlayer[G.SOUND_GAME_WIN].isPlaying()) {
G.soundPlayer[G.SOUND_GAME_WIN].seekTo(0);
} else {
G.soundPlayer[G.SOUND_GAME_WIN].start();
}
break;
case G.SOUND_GAME_STRESS:
if (G.soundPlayer[G.SOUND_GAME_STRESS].isPlaying()) {
G.soundPlayer[G.SOUND_GAME_STRESS].seekTo(0);
} else {
G.soundPlayer[G.SOUND_GAME_STRESS].start();
}
break;
case G.SOUND_FIRE_END:
if (G.soundPlayer[G.SOUND_FIRE_END].isPlaying()) {
G.soundPlayer[G.SOUND_FIRE_END].seekTo(0);
} else {
G.soundPlayer[G.SOUND_FIRE_END].start();
}
break;
}
}
}
و بعد از توی کلاس های مختلف تابع استاتیک playSFX رو صدا میزنم مثلا به این شکل:
G.playSFX(G.SOUND_FIRE_END);
حالا مشکل عجیب اینجاست که فقط آخرین mediaPlayer ای که اضافه کردم وارد آرایه نمیشه!(با این که آرایه به اندازست!)
و خیلی عجیب تر از اون این که اگر توی onCreate خطی که مربوط به مقدار دهی اخرین mediaPlayer میشه (خط اخر قبل super) رو ببرم و اول onCreate قرار بدم دیگه موقع اجرا این mediaPlayer خطا نمیده ولی دقیقا mediaPlaye قبلیش یعنی :
soundPlayer[G.SOUND_GAME_STRESS] = MediaPlayer.create(G.this, R.raw.game_stress);
موقع اجرا null pointer exeption میده!
برای من خیلی عجیبه ولی این اتفاق میفته و من دیشب تا صپ نتونستم حلش کنم از قرار گرفتن فایل های صوتی توی فولدر raw و همینطور نام گذاری صحیح فایل ها هم مطمن هستم!
احتمالا نکته ای وجود داره که من بی اطلاع باشم ازش و دلیل این مشکل باشه؟
مرسی از وقتتون :)
دوست عزیز سلام و خسته نباشید
اگر شما بر روی استفاده از کد های خودتان پافشاری میکنید متاسفانه نمیتوانم کمکی بکنم !
اما اگر قصد ایجاد یک پلیر و بخش چندین اهنگ را دارید (به دلیل اشاره شما به ارایه ) میتوانید از لینک بسیار مفیدو سالم و تست شده ی زیر استفاده بکنید . موفق باشید
خب مشکل حل شد توضیحاتشو میذارم شاید بعدا به درد دیگران هم بخوره:
توی stackoverflow میگشتم که به اینجمله برخوردم (ترجمش نمیکنم چون انگلیسیم افتضاحه :دی)
Since a number of low-level resources might be allocated for each MediaPlayer,
it could be that if the GC is busy for a while or doesn't run
you'll run out of sound buffers (or whatever) and the MediaPlayer allocation will fail,
returning null.
و ایراد کار من دقیقا همین بود که 8 تا mediaPlayer درست میکردم و تو کل برنامه اشغالشون میکردم این کار برای گوشی هایی که sound buffer با ظرفیت کمتری دارن باعث null شدن mediaPlayer موقع تخصیص فایل میشه !پس میشه به جای مصرف بی رویه ی بافر صوتی با یک مدیا پلیر (البته به شرط تداخل نداشتن زمان اجرا) چندین افکت صوتی رو پخش کرد که من هر بار قبل از استفاده به شکل زیر فایل ریسورسش رو تغیر دادم :
if (soundPlayer[G.SOUND_SHARED] != null) {
soundPlayer.release();
soundPlayer = null;
}
G.soundPlayer = MediaPlayer.create(G.currentActivity, R.raw.sample_next_music);
G.soundPlayer.start();
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .