Android MediaPlayer use lot of resource - android

I'm making game in OpenGL 2.0 and I have problems with sounds, because sounds slow down my application and FPS decrease about 20 frames. I implement service for sounds and run it on new thread, but problem is same. MediaServer use more CPU than my application with lot of sprites.
I play only three sounds with total size less than 0.5 MB.
This is my code:
package com.filsoft.mouse;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
public class Sound extends Service implements OnCompletionListener {
private final IBinder mBinder = new LocalBinder();
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
MediaPlayer[] mediaPlayer=new MediaPlayer[3];
public ServiceHandler(Looper looper) {
super(looper);
mediaPlayer[0] = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
mediaPlayer[0].setLooping(true);
mediaPlayer[1] = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
mediaPlayer[1].setLooping(true);
mediaPlayer[2] = MediaPlayer.create(getApplicationContext(), R.raw.sound1);
mediaPlayer[2].setLooping(true);
try {
for(int i=0;i<3;i++)
mediaPlayer[i].prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void handleMessage(Message msg) {
play(msg.arg1);
}
public void stopAll()
{
if (mediaPlayer[0].isPlaying()) {
mediaPlayer[0].pause();
}
if (mediaPlayer[1].isPlaying()) {
mediaPlayer[1].pause();
}
if (mediaPlayer[2].isPlaying()) {
mediaPlayer[2].pause();
}
}
public void play(int idx)
{
stopAll();
if (!mediaPlayer[idx].isPlaying()) {
mediaPlayer[idx].start();
}
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("Audio",
Process.THREAD_PRIORITY_URGENT_AUDIO);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
public void startPlay(int idx)
{
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = idx;
mServiceHandler.sendMessage(msg);
}
public class LocalBinder extends Binder {
public Sound getService() {
return Sound.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void onDestroy() {
}
public void onCompletion(MediaPlayer _mediaPlayer) {
stopSelf();
}
}

Instead of creating multiple MediaPlayers, you should use a SoundPool - a class specifically designed to play multiple streams simultaneously such as found in games. Looping sounds is also very easy:
Sounds can be looped by setting a non-zero loop value. A value of -1 causes the sound to loop forever. In this case, the application must explicitly call the stop() function to stop the sound. Any other non-zero value will cause the sound to repeat the specified number of times, e.g. a value of 3 causes the sound to play a total of 4 times.

Related

Guarantee only one timerTasks with threads in service

My Android application has a service, that will be created at timer task with specified interval. The task should check out webservice by async task, if the Internet is enabled, send some informations, otherwise it should wait (for example, 5 seconds) and check connection again.
My problem is: how to prevent creating tasks while timertask is waiting?
I wish that at any time there is only one task working.
My code:
mTimer.scheduleAtFixedRate(new MyTask(), 0, 10000); //creating tasks in service
class MyTask extends TimerTask {
#Override
public void run() {
if (!isLocked) {
new Thread(new Runnable() {#Override
public void run() {
isLocked = true;
if (!isInternet) {
do {
Log.v("TestService", "Waiting...");
SystemClock.sleep(5000);
isInternet = getInternetConn();
} while (!isInternet);
} else {
//do work
}
isLocked = false;
}).run();
}
}
}
I would suggest you to follow this process, which i have used for getting GCM_Registration id, same as you can use it check your internet connection.
which works like : in onStartCommand(), mServiceHandler.sendMessage(msg); starts a asynctask which check does we have GCM-ID if yes we stop the service and if no, then we again check for GCM-ID by asynctask.
package com.urbanft.utils;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.text.TextUtils;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.urbanft.app.GlobalPreference;
public class GCMIdFetchService extends Service {
private final String SENDER_ID = "916449540455";
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private static final long INTERVAL = 1000;
private GoogleCloudMessaging mGoogleCloudMessaging;
private String mRegisterationId;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg){
new GCMIdFetchSearviceTask().execute("");
}
}
protected void initialization() {
mGoogleCloudMessaging = GoogleCloudMessaging.getInstance(getApplicationContext());
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
}
class GCMIdFetchSearviceTask extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params) {
getGCMID();
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
String gcmId = GlobalPreference.getInstance(getApplicationContext()).getGCMRegistrationId();
if(!TextUtils.isEmpty(gcmId)){
stopSelf();
return;
}
new Handler().postDelayed(new Runnable() {
public void run() {
Message msg = mServiceHandler.obtainMessage();
mServiceHandler.sendMessage(msg);
}
}, INTERVAL);
}
}
private void getGCMID() {
try{
if(mGoogleCloudMessaging == null){
mGoogleCloudMessaging = GoogleCloudMessaging.getInstance(getApplicationContext());
}
mRegisterationId = mGoogleCloudMessaging.register(SENDER_ID);
GlobalPreference.getInstance(getApplicationContext()).setGCMRegistrationId(mRegisterationId);
}
catch (IOException err){
err.printStackTrace();
}
}
}

IntentService Thread.sleep() limit?

i was wondering if the IntentService has thread blocking limit like calling Thread.sleep(); and if so what's the maximum time limit for it?
so i wrote the following code snippet:
package net.yassin.aaaservice;
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.SystemClock;
import android.widget.Toast;
public class MyService extends IntentService {
private Thread t;
private static int i = 0;
private static final int SLEEP_DURATION = 2000;
private Handler handler;
public MyService() {
super("MyService");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
this.handler = new Handler();
}
#Override
protected void onHandleIntent(Intent arg0) {
this.t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
MyService.this.handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyService.this,
"This is toast #" + (++i),
Toast.LENGTH_SHORT).show();
}
});
try {
Thread.sleep(SLEEP_DURATION);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
this.t.start();
}
}
and i found that whenever i change the time SLEEP_DURATION constant to over than 2000 Milis the service will stop showing Toasts if i removed the app form the recent menu?
am i right or there is another time limit or behavior ?
thnx :)

MediaPlayer's SetOnCompletionListener is not working

m using service to play a audio file in background.
This is my PreviewServices class .
package com.hungama.myplay.activity;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.MediaController;
import android.widget.Toast;
public class PreviewServices extends Service {
private static final String TAG = "PreviewServices";
public static MediaPlayer player;
protected DataManager dataManager = DataManager.getInstance();
String song_uri, url;
private IBinder myBinder;
private boolean isplaying;
#Override
public IBinder onBind(Intent intent) {
return null;
}
public class MyBinder extends Binder {
PreviewServices getService() {
return PreviewServices.this;
}
}
#Override
public void onCreate() {
Log.d(TAG, "onCreate " + song_uri);
}
#Override
public void onDestroy() {
player.stop();
}
public void onPause() {
player.pause();
}
public double duration() {
return player.getDuration();
}
public void onStart(Intent intent, int startid) {
Bundle b = intent.getExtras();
song_uri = b.getString("song_uri");
Uri path = Uri.parse(song_uri);
player = MediaPlayer.create(this, path);
player.setLooping(false); // Set looping
player.start();
/ *player.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
Log.d("song is completed","song is not playing now");
dataManager.setPreview_play(true);
}
});
*/
}
}
My PreviewServices is working fine,
in My Activity i want to show a message when my song will complete.
m using this code for this purpose.
PreviewServices preview=new PreviewServices();
MusicScreen.this.preview.player.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
Log.d("song is complete","song complete");
}
});
I dont know Y its throws Null Pointer Exception in this line
MusicScreen.this.preview.player.setOnCompletionListener(new OnCompletionListener()
please suggest me where is problem.
thanks in advance.
Gaurav Gupta
I'm sure you'll get more responses if your code is displayed properly. Every line of code needs to have four spaces or a tab at the start of it. Try editing to fix it.
A simple thing you can do is break up the line like this (where you specify appropriate classes for x, y and z):
x = MusicScreen.this
y = x.preview
z = y.player
z.setOnCompletionListener(ETC.
Then you can see where it breaks down. Other than that, I don't understand your program so I can't help...

Android: Instantiate a Handler in a TimerTask within a Service

I'm trying to use a service to make a regular call to my API. The asynchronous class I use to make external HTTP calls returns information to a handler which is passed in.
A simplified version below dies on the line where the Handler is instantiated (without a stack trace). Any idea why? Is there a better way I should be doing this?
package com.fred.services;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class NotificationService extends Service {
private static final String TAG = "com.fred.services NotificationService";
public long delay = 0;
public long period_in_minutes = 10;
public long period = 1000*60*period_in_minutes;
private Timer timer = null;
private TimerTask task = new TimerTask() {
#Override
public void run() {
Handler h;
Log.i(TAG, "now you see it");
h = new Handler();
Log.i(TAG, "now you don't");
}
};
#Override
public void onCreate(){
super.onCreate();
if (timer == null) startservice();
}
private void startservice() {
if (timer == null) timer = new Timer();
timer.scheduleAtFixedRate(task, delay, period);
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
Is there a better way I should be doing this?
Use AlarmManager and an IntentService. This allows your code to stay out of memory except during the moments when it is actually adding value to the user (i.e., accessing your Web service).

How can we call an activity through service in android?

I want to know if it is possible to call an activity through background service in android like :
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
public class background extends Service{
private int timer1;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
SharedPreferences preferences = getSharedPreferences("SaveTime", MODE_PRIVATE);
timer1 = preferences.getInt("time", 0);
startservice();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
private void startservice() {
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run() {
mediaPlayerPlay.sendEmptyMessage(0);
}
}, timer1*60*1000);
}
private Handler mediaPlayerPlay = new Handler(){
#Override
public void handleMessage(Message msg) {
try
{
getApplication();
MediaPlayer mp = new MediaPlayer();
mp = MediaPlayer.create(background.this, R.raw.alarm);
mp.start();
}
catch(Exception e)
{
e.printStackTrace();
}
super.handleMessage(msg);
}
};
/*
* (non-Javadoc)
*
* #see android.app.Service#onDestroy()
*/
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
i want to call my activity......
You can call an Activity while onStart() of your service.....
Snippet might be as follows:
#Override
public void onStart(Intent intent, int startId) {
...
Log.i("Service", "onStart() is called");
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(<Set your package name and class name here>);
startActivity(callIntent);
...
}
I believe launching user-interactive Activity from a non-interactive Service goes against the design of Android, in that it would pull out control from under the user.
Notifications are the mechanism intended to get user's attention from a background app, and give them an opportunity to launch the interactive Activity.

Categories

Resources