overriden onPrepared not being called automatically - java

The following is the service class of my music player, the implemented onPrepared() method is never called, so I have to use setOnPreparedListener to get the things done.
I want to execute it from the unimplemented section.
public class MusicService extends Service implements MediaPlayer.OnPreparedListener,
MediaPlayer.OnErrorListener,MediaPlayer.OnCompletionListener {
//media player
private MediaPlayer player;
//song list
private ArrayList<Song> songs;
//current position
private int songPosn;
private String songTitle="";
private static final int NOTIFY_ID=1;
private final IBinder musicBind = new MusicBinder();
#Override
public IBinder onBind(Intent intent) {
return musicBind;
}
public boolean onUnbind(Intent intent){
player.stop();
player.release();
return false;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
//initialize position
songPosn = 0;
//create player
player = new MediaPlayer();
}
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
return false;
}
//this is never being called and instead of this the one in setOnPreparedListener is called
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
//start music
mp.start();
Intent notIntent = new Intent(this, MainActivity.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendInt = PendingIntent.getActivity(this, 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(pendInt)
.setSmallIcon(R.drawable.play)
.setTicker(songTitle)
.setOngoing(true)
.setContentText("Playing")
.setContentText(songTitle);
Notification not = builder.build();
startForeground(NOTIFY_ID, not);
}
public void initMusicPlayer(){
//set player properties
player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
public void setSong(int songIndex){
songPosn=songIndex;
}
public void setList(ArrayList<Song> theSongs){
songs = theSongs;
}
public void playSong(){
//play a cool song
player.reset();
//get song
Song playSong = songs.get(songPosn);
songTitle = playSong.getTitle();
//get ID
long currSong = playSong.getId();
//set path to sdcard or squaremash server
Uri trackUri = ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, currSong);
try {
player.setDataSource(getApplicationContext(), trackUri);
} catch (Exception e) {
Log.e("Music service","Error: setting data source",e); }
player.prepareAsync();
//this one is called, If I remove this, the above onPrepared method isnt called
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.start();
}
});
}
public void go(){
player.start();
}
//previous song
public void playPrev() {
songPosn--;
if(songPosn<0)
songPosn=songs.size()-1;
playSong();
}
//next song
public void playNext() {
songPosn++;
if(songPosn>=songs.size())
songPosn=0;
playSong();
}
}

This is not how Java works.
You're extending a Service object. There is nothing in that object's lifecycle that triggeres a call to onPrepared(). What triggers that call is your player member:
private MediaPlayer player;
And for that to happen, i.e. for player to trigger a call to onPrepared(), you need to point it to an object implementing onPrepared(). This object is your MusicService object, thus you need to call:
player.setOnPreparedListener(this);

You don't set the correct OnPreparedListener.
In onCreate() when you create the player, you should set the listener there:
player = new MediaPlayer();
player.setOnPreparedListener(this)
And remove the other one, otherwise it'll override the first.
When you implement an interface, it's just setting a contract on the class: "this class has these particular methods, feel free to call them". MediaPlayer needs to know which OnPreparedListener to use (MediaPlayer.setOnPreparedListener) otherwise it won't do anything.

Related

How to prevent music to stop after the phone's screen goes off?

I am making an application which play background music. And when my phone's screen goes off(or sleep) then the music stops and I want it to also play after the screen goes's off.
This is My code.
MediaPlayer ring= MediaPlayer.create(MainActivity.this,R.raw.backgroundmusic);
ring.start();
ring.setLooping(true);
MediaPlayer class can be used to control playback of audio/video files and streams. An example on how to use the methods in this class can be found in VideoView.
MediaPlayer
public class SoundService extends Service {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.idil);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
}
public void onPause() {
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
Intent svc=new Intent(this, SoundService.class);
startService(svc);
Make sure You've added your service to the menifest.
<service android:enabled="true" android:name=".SoundService" />
You should consider using Service.

Android KeyEvents from Service API22

Asking in the name of a friend because I already have an account with rep.
"I have a small project going on that is supposed to activate my phone's flashlight when I press the volume up button and disable it when I press the volume down button. This is so I can easily access the flashlight even when wearing gloves. My problem here is that the app should be running as a service in the background and work when the screen is turned off and that is not possible... or so it seems."
What we have tried:
Background Activity
Media Session
Compiling SDL C++ and polling Keys from there
Broadcast Reciever
But none of these worked.
Here is the current version of the service file:
//imports
public class FlashService extends Service {
public static final String BROADCAST = "android.intent.action.MEDIA_BUTTON";
private static final String TAG = "OutdoorFlashlightService";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_REDELIVER_INTENT;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#SuppressWarnings("deprecation")
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.w(TAG, "Service started!");
MediaSession _mediaSession = new MediaSession(getApplicationContext(), TAG);
if (_mediaSession == null) {
Log.e(TAG, "initMediaSession: _mediaSession = null");
return;
}
Token _mediaSessionToken = _mediaSession.getSessionToken();
_mediaSession.setCallback(new Callback() {
public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
Log.d(TAG, "onMediaButtonEvent called: " + mediaButtonIntent);
return super.onMediaButtonEvent(mediaButtonIntent);
}
public void onPause() {
Log.d(TAG, "onPause called (media button pressed)");
super.onPause();
}
public void onPlay() {
Log.d(TAG, "onPlay called (media button pressed)");
super.onPlay();
}
public void onStop() {
Log.d(TAG, "onStop called (media button pressed)");
super.onStop();
}
});
_mediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
PlaybackState state = new PlaybackState.Builder().setActions(PlaybackState.ACTION_PLAY)
.setState(PlaybackState.STATE_STOPPED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0).build();
_mediaSession.setPlaybackState(state);
_mediaSession.setActive(true);
}
}
Here is the failed attempt at a BroadcastReciever, that never actually recieved anything:
package de.platzhirsch.outdoorflashlight;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.util.Log;
import android.view.KeyEvent;
#SuppressWarnings("deprecation")
public class MyBroadcastReceiver extends BroadcastReceiver {
private Camera cam;
private boolean lighting = false;
public MyBroadcastReceiver() {
super();
Log.w("", "Receiver registered!");
}
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.w("", "Got msg!");
String intentAction = intent.getAction();
KeyEvent event = null;
if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
}
if (event == null) {
return;
}
Log.w("", "triggered...");
int keycode = event.getKeyCode();
int action = event.getAction();
long eventtime = event.getEventTime();
if (event.getAction() == KeyEvent.ACTION_DOWN) {
Camera.Parameters parameters;
if (cam == null) {
cam = Camera.open();
}
switch (keycode) {
case KeyEvent.KEYCODE_VOLUME_UP:
if (!lighting) {
parameters = cam.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(parameters);
cam.startPreview();
lighting = true;
}
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (lighting) {
parameters = cam.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cam.setParameters(parameters);
cam.stopPreview();
cam.release();
cam = null;
lighting = false;
}
break;
}
}
}
}
What we are looking for is really just a way to get the Volume KeyEvents to the service
Note: The app is only intended to run on my friend's device so if all else fails a dirty device specific solution with Hardware IDs will suffice

Service and Notification refreshed when Activity is closed

I have a Service with a Notification with a Progress Bar inside. This Service is started when i open the Main Activity and works fine. But, when i close Main Activity (onDestroy() is called) the Notification is like refreshed. This is the code of my Service.
#Override
public void onCreate() {
super.onCreate();
Mypreferences prefs = new Mypreferences(this);
String minutes = prefs.getStringValueOf("Minutes");
final NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
d = Integer.valueOf(minutes)*60;
builder.setSmallIcon(R.drawable.ic_action_about);
builder.setContentTitle(getString(R.string.app_name));
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<d;i++) {
builder.setProgress(d, d-i, false);
builder.setContentInfo(d-i+"/"+d);
notificationManager.notify(0, builder.build());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
Integer d it's 60 and countdown works fine but when i close MainActivity if for example ProgressBar is at 40, return to 60. Why? How can i solve?
Service code
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
pref = new SharedPref(this);
map = pref.getAllPrefs();
boolean delay = pref.loadBooleanPref("delay");
String delayTime = pref.loadStringValue("DelayTime");
if(delay && delayTime != null) {
new CountDownTimer(TimeUnit.MINUTES.toMillis(Long.valueOf(delayTime)), 1000) {
#Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
getInfo();
}
}.start();
} else {
getInfo();
}
}

How to use AIDL services for updating counter value?

I am new to android. I am trying using AIDL.
What I am tryng is take initial value i.e 0 from the Textview and tryng to increment its value by calling a method defined in aidl file(using service.)
But the TextView is not updating on button click.
Kindly Help.
Here is my code.
CounterService.aidl
package com.example.counter;
interface CounterService {
int updateCounter(in int var);
}
CounterServ.java (Exposing service)
package com.example.counter;
public class CounterServ extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return new CounterService.Stub() {
#Override
public int updateCounter(int var) throws RemoteException {
// TODO Auto-generated method stub
return var + 1;
}
};
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
User Activity using service.
public class MainActivity extends Activity {
CounterService myservice;
AdditionServiceConnection connection;
class AdditionServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder Service) {
myservice = CounterService.Stub.asInterface(Service);
Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_LONG)
.show();
}
public void onServiceDisconnected(ComponentName name) {
myservice = null;
Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_LONG)
.show();
}
}
private void initService() {
connection = new AdditionServiceConnection();
Intent i = new Intent();
i.setClassName("com.example",com.example.counter.MainActivity.class.getName());
boolean ret = bindService(i, connection, Context.BIND_AUTO_CREATE);
}
private void releaseService() {
unbindService(connection);
connection = null;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initService();
Button update = (Button)findViewById(R.id.button1);
update.setOnClickListener(new View.OnClickListener() {
TextView value=(TextView)findViewById(R.id.textView1);
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int val,res=-1;
val=Integer.parseInt(value.getText().toString());
try{
res=myservice.updateCounter(val);
}
catch(Exception e)
{e.printStackTrace();}
value.setText(res);
}
});
}
protected void onDestroy() {
releaseService();
}
}
Convert res into text format by applying following code and try
String str = String.valueOf(res);
value.setText(str);
I got where I was lacking. I didnt register this service in the menifest file and therefore was not able to use it.

android call listener from service will not respond when activity closes

I am creating application which contains service that suppose to listen to calls,
and pop up an alert dialog after call has ended, the issue is, that as long as the activity running or in the background, the service works and the dialog pop up, but when I close the activity, the dialog wont pop up, as like the listener will not listen anymore to calls.
need help please!
this is how I call the service from my activity:
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
startService(new Intent(getBaseContext(), PhoneService.class));
break;
case R.id.stop:
stopService(new Intent(getBaseContext(), PhoneService.class));
break;
}
}
the service class:
public class PhoneService extends Service {
private static String TAG = "SERVICE";
int currentState;
Context context;
String incomingNumber;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
// starts the service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "FirstService started");
context = this;
TelephonyManager telephony = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); // TelephonyManager
// object
CallListener listener = new CallListener();
telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
// keeps the service going until explicitly stops
return START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.i(TAG, "FirstService destroyed");
}
the listener class:
public class CallListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
// Incoming call handling
Log.i(TAG, " ring ring ring" + incomingNumber);
currentState = state;
}
if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
// Outgoing call handling and answer
Log.i(TAG, " ofhook" + incomingNumber);
currentState = state;
}
if (TelephonyManager.CALL_STATE_IDLE == state) {
// Device back to normal state (not in a call)
Log.i(TAG, " idle" + incomingNumber);
if (currentState == TelephonyManager.CALL_STATE_OFFHOOK) {
Toast.makeText(context,"phone number dialed is "+ PhoneService.this.incomingNumber,Toast.LENGTH_SHORT).show();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Who is this person?").setCancelable(false).setPositiveButton("1",new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface dialog, int id) {
}
})
.setNegativeButton("0",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
alert.getWindow().setType(
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alert.show();
}
currentState = state;
}
}
}
Change your service to derive from IntentService and remove the overrides for onBind and onStartCommand (let the system handle those).
Put your code in the onHandleIntent override.
The different service types are handled differently - a bound service only operates while the activity is running, but an intent service can be started at any time. You can read more about service types here.

Categories