I've got a service which is passed a bundle of variables (song, artist album etc.), and includes a MediaPlayer, and a bunch of methods for that MediaPlayer (play next, previous etc.).
I've also got an activity, which displays the UI to the user, including next/previous buttons, a Seekbar, and the display of the artist/album/song.
What I'd like to know is how to get the UI activity to make changes to the service, and the service to update the activity depending on which song is selected..
For example: An artist/album/song combination is sent to the service. The service tells a MediaPlayer to begin playing that song. The song title/album/artist is displayed in the activity, and the user can press play/pause etc in the UI. Upon clicking, the service will act accordingly.
I don't know how to get all these things happening, and I'm getting caught up with broadcasts and intents and statics.. I would really appreciate some clear guidance, and a good example of how this could be done.
Thank you for your patience & help.
Please find the code below:
MusicService.java:
package awesome.music.player;
import java.io.IOException;
import java.util.ArrayList;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnSeekCompleteListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
public class MusicService extends Service implements OnCompletionListener,
OnSeekCompleteListener {
Intent intent;
MediaPlayer mediaPlayer = new MediaPlayer();
String isComplete;
String serviceStatus;
String sntSeekPos;
String artist;
String selection;
String album;
String numSongs;
int albumId;
String currentSongPath;
String[] selectionArgs;
Uri currentSongUri;
int songEnded;
int currentSongIndex;
int totalSongDuration;
int intSeekPos;
int mediaPosition;
int mediaMax;
ArrayList<String> pathList;
ArrayList<String> artistList;
ArrayList<String> albumList;
ArrayList<String> titleList;
ArrayList<String> idList;
ArrayList<String> durationList;
private final Handler handler = new Handler();
public final String BROADCAST_ACTION = "awesome.music.player.seekprogress";
public final String BROADCAST_OTHER = "awesome.music.player.displaysong";
Intent seekIntent;
Intent displayIntent;
Utilities utils;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.intent = intent;
Bundle extras = intent.getExtras();
artist = extras.getString("artist");
selection = extras.getString("selection");
selectionArgs = extras.getStringArray("selectionArgs");
album = extras.getString("album");
albumId = extras.getInt("albumId");
numSongs = extras.getString("numSongs");
currentSongIndex = extras.getInt("currentSongIndex");
currentSongPath = extras.getString("currentSongPath");
totalSongDuration = extras.getInt("totalSongDuration");
pathList = extras.getStringArrayList("pathList");
artistList = extras.getStringArrayList("artistList");
albumList = extras.getStringArrayList("albumList");
titleList = extras.getStringArrayList("titleList");
idList = extras.getStringArrayList("idList");
durationList = extras.getStringArrayList("durationList");
prepareSong(currentSongPath);
playSong();
displaySong();
utils = new Utilities();
seekIntent = new Intent(BROADCAST_ACTION);
displayIntent = new Intent(BROADCAST_ACTION);
setupHandler();
return START_STICKY;
}
/*
* #Override public void onCreate() { super.onCreate();
*
* utils = new Utilities();
*
* seekIntent = new Intent(BROADCAST_ACTION);
*
* setupHandler();
*
* prepareSong(currentSongPath); playSong(); }
*/
public void prepareSong(String currentSongPath) {
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(currentSongPath);
mediaPlayer.prepare();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void playSong() {
try {
mediaPlayer.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onCompletion(MediaPlayer mediaPlayer) {
playNext();
}
#Override
public void onStart(Intent intent, int startId) {
registerReceiver(broadcastReceiver, new IntentFilter(
MusicPlayer.BROADCAST_SEEKBAR));
super.onCreate();
prepareSong(currentSongPath);
playSong();
}
private void setupHandler() {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
LogMediaPosition();
handler.postDelayed(this, 1000);
}
};
private void LogMediaPosition() {
if (mediaPlayer.isPlaying()) {
mediaPosition = mediaPlayer.getCurrentPosition();
MusicPlayer.currentDurationLabel.setText(""
+ utils.milliSecondsToTimer(mediaPosition));
mediaMax = mediaPlayer.getDuration();
seekIntent.putExtra("counter", String.valueOf(mediaPosition));
seekIntent.putExtra("mediamax", String.valueOf(mediaMax));
seekIntent.putExtra("song_ended", String.valueOf(songEnded));
sendBroadcast(seekIntent);
}
}
private void displaySong() {
utils = new Utilities();
String title = titleList.get(currentSongIndex);
String artist = artistList.get(currentSongIndex);
String album = albumList.get(currentSongIndex);
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri currentSongUri = ContentUris.withAppendedId(sArtworkUri, albumId);
String totalDuration = utils.milliSecondsToTimer(totalSongDuration);
mediaPosition = mediaPlayer.getCurrentPosition();
MusicPlayer.currentDurationLabel.setText(""
+ utils.milliSecondsToTimer(mediaPosition));
displayIntent.putExtra("title", title);
displayIntent.putExtra("artist", artist);
displayIntent.putExtra("album", album);
displayIntent.putExtra("totalDuration", totalDuration);
displayIntent.putExtra("currentSongUri", currentSongUri);
sendBroadcast(displayIntent);
}
// receive seekbar position
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateSeekPos(intent);
}
};
// Update seek position from Activity
public void updateSeekPos(Intent intent) {
int seekPos = intent.getIntExtra("seekpos", 0);
if (mediaPlayer.isPlaying()) {
handler.removeCallbacks(sendUpdatesToUI);
mediaPlayer.seekTo(seekPos);
setupHandler();
}
}
#Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
handler.removeCallbacks(sendUpdatesToUI);
// Unregister seek receiver
unregisterReceiver(broadcastReceiver);
}
public void onSeekComplete(MediaPlayer mediaPlayer) {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
public void playNext() {
if (mediaPlayer.isPlaying()) {
if (currentSongIndex < (pathList.size() - 1)) {
currentSongIndex = currentSongIndex + 1;
currentSongPath = pathList.get(currentSongIndex);
prepareSong(currentSongPath);
playSong();
} else {
currentSongIndex = 0;
currentSongPath = pathList.get(currentSongIndex);
prepareSong(currentSongPath);
playSong();
}
} else {
if (currentSongIndex < (pathList.size() - 1)) {
currentSongIndex = currentSongIndex + 1;
currentSongPath = pathList.get(currentSongIndex);
prepareSong(currentSongPath);
} else {
currentSongIndex = 0;
prepareSong(currentSongPath);
}
}
displaySong();
}
void playPrevious() {
if (mediaPlayer.isPlaying()) {
if (currentSongIndex > 0) {
currentSongIndex = currentSongIndex - 1;
currentSongPath = pathList.get(currentSongIndex);
prepareSong(currentSongPath);
playSong();
} else {
currentSongIndex = pathList.size() - 1;
currentSongPath = pathList.get(currentSongIndex);
prepareSong(currentSongPath);
playSong();
}
} else {
if (currentSongIndex > 0) {
currentSongIndex = currentSongIndex - 1;
currentSongPath = pathList.get(Playlist.currentSongIndex);
prepareSong(currentSongPath);
} else {
currentSongIndex = pathList.size() - 1;
currentSongPath = pathList.get(currentSongIndex);
prepareSong(currentSongPath);
}
}
displaySong();
}
}
MusicPlayer.java:
package awesome.music.player;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class MusicPlayer extends Activity implements OnSeekBarChangeListener {
public ImageButton play;
public ImageButton next;
public ImageButton previous;
public static ImageView albumArt;
static TextView songArtistAlbumLabel;
static TextView songTitleLabel;
static TextView currentDurationLabel;
static TextView totalDurationLabel;
static String serviceStatus;
private SeekBar seekBar;
private int seekMax;
boolean mBroadcastIsRegistered;
public static Utilities utils;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playing);
play = (ImageButton) findViewById(R.id.playButton);
next = (ImageButton) findViewById(R.id.nextButton);
previous = (ImageButton) findViewById(R.id.previousButton);
albumArt = (ImageView) findViewById(R.id.imageView1);
songArtistAlbumLabel = (TextView) findViewById(R.id.songArtistAlbumLabel);
songTitleLabel = (TextView) findViewById(R.id.songTitleLabel);
totalDurationLabel = (TextView) findViewById(R.id.totalDurationLabel);
songArtistAlbumLabel = (TextView) findViewById(R.id.songArtistAlbumLabel);
play.setOnClickListener(playListener);
next.setOnClickListener(nextListener);
previous.setOnClickListener(previousListener);
seekBar = (SeekBar) findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(this);
intent = new Intent(BROADCAST_SEEKBAR);
if (mBroadcastIsRegistered != true) {
registerReceiver(broadcastReceiver, new IntentFilter(
MusicService.BROADCAST_ACTION));
;
mBroadcastIsRegistered = true;
}
}
private OnClickListener playListener = new OnClickListener() {
public void onClick(View v) {
MusicService.playSong();
}
};
private OnClickListener nextListener = new OnClickListener() {
public void onClick(View v) {
MusicService.playNext();
}
};
private OnClickListener previousListener = new OnClickListener() {
public void onClick(View v) {
MusicService.playPrevious();
}
};
public static final String BROADCAST_SEEKBAR = "awesome.music.player.sendseekbar";
Intent intent;
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent serviceIntent) {
updateUI(serviceIntent);
}
};
private void updateUI(Intent serviceIntent) {
String counter = serviceIntent.getStringExtra("counter");
String mediamax = serviceIntent.getStringExtra("mediamax");
String strSongEnded = serviceIntent.getStringExtra("song_ended");
int seekProgress = Integer.parseInt(counter);
seekMax = Integer.parseInt(mediamax);
Integer.parseInt(strSongEnded);
seekBar.setMax(seekMax);
seekBar.setProgress(seekProgress);
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser) {
int seekPos = seekBar.getProgress();
intent.putExtra("seekpos", seekPos);
sendBroadcast(intent);
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
playing.xml:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<SeekBar
android:id="#+id/seekBar"
android:layout_width="296dp"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_x="10dp"
android:layout_y="446dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:progressDrawable="#drawable/seekbar_progress"
android:thumb="#drawable/seek_handler" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="37dp"
android:layout_height="37dp"
android:layout_x="6dp"
android:layout_y="397dp"
android:src="#drawable/ic_tab_albums_white" />
<TextView
android:id="#+id/songTitleLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="55dp"
android:layout_y="395dp"
android:text="Song Label"
android:textSize="20sp" />
<TextView
android:id="#+id/songArtistAlbumLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="55dp"
android:layout_y="417dp"
android:text="Artist - Album Label"
android:textSize="15sp" />
<TextView
android:id="#+id/currentDurationLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="10dp"
android:layout_y="481dp"
android:text="0:00" />
<TextView
android:id="#+id/totalDurationLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="281dp"
android:layout_y="477dp"
android:text="3:30" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="41dp"
android:layout_y="312dp"
android:gravity="center_horizontal" >
<ImageButton
android:id="#+id/previousButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="132dp"
android:layout_y="308dp"
android:src="#drawable/ic_previous" />
<ImageButton
android:id="#+id/playButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50sp"
android:layout_marginRight="50sp"
android:src="#drawable/ic_pause" />
<ImageButton
android:id="#+id/nextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_next" />
</LinearLayout>
<ImageView
android:id="#+id/imageView1"
android:layout_width="287dp"
android:layout_height="272dp"
android:layout_x="16dp"
android:layout_y="13dp"
android:background="#drawable/dummy_album_art"
android:scaleType="fitXY" />
</AbsoluteLayout>
as general
there a three main ways to commnicate with Services
1-Binder (in bind service)
2-Messenger
3-AIDL
On Android, one process cannot normally access the memory of another process. So to talk,
they need to decompose their objects into primitives that the operating system can
understand, and marshall the objects across that boundary for you. The code to do that
marshalling is tedious to write, so Android handles it for you with AIDL.
Using AIDL is necessary only if
1- you allow clients from different applications to access your service for IPC
2- you want to handle multithreading in your service. If you do not need to perform concurrent IPC
across different applications,
Using Binder
you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need
Using Messenger
to handle multithreading, implement your interface using a Messenger.
http://developer.android.com/guide/developing/tools/aidl.html
http://java.dzone.com/articles/android-aidl-and-remote-client
other then this can use
1- Broadcasting intent from service
2 -
You have to make a playback service that starts when the application is created you can start our service from a class that extends Application.
You can use aidl to communicate a service with activity.As activity is already startedit cant get killed when the activity stops.
You can use Mediastore content resolver to get data about tracks there artists albums etc..
MediaStore.Audio.Media.* Columns you want it provide all data and also path of the song
4.I am also currently in process of building player.......but all this is working as i use it
Related
I have an android app with a detail activity, that detail activity has few tabs with underlying fragments. One of these fragments is plain list with a name of audio files when I click each line I'm playing the clicked audio files.
Everything works OK, but I would like to have some means of seeing a progress of the playback and ability to stop a playback, I was trying to add MediaController but even though I'm creating it without errors no media control is visible on a screen.
I'm not sure if I'm doing it in a correct way any help you would be appreciated.
Thanks a lot,
Radek
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
try {
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.audio_row,parent,false);
}
TextView textView = (TextView) convertView.findViewById(R.id.rowText);
textView.setText("" + jsonAudio.getJSONObject(position).getString("description"));
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
String audioFileName = jsonAudio.getJSONObject(position).getString("file");
Toast.makeText(context, "audio item clicked: " + audioFileName, Toast.LENGTH_SHORT).show();
AssetFileDescriptor descriptor = context.getAssets().openFd(audioFileName);
long start = descriptor.getStartOffset();
long end = descriptor.getLength();
MediaPlayer mediaPlayer=new MediaPlayer();
mediaPlayer.setDataSource(descriptor.getFileDescriptor(), start, end);
mediaPlayer.prepare();
// not doing really anything
MediaController mediaController = new MediaController(context);
mediaController.setAnchorView(v);
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
Please check the below code for your refrence
In your code you have passed the TextView in the mediaController need to pass the SurfaceView instead of TextView and you need to set the MediaPlayer in the MediaController
JAVA file.
import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; import android.util.Log;
import android.media.MediaPlayer.OnPreparedListener; import android.view.MotionEvent; import android.widget.MediaController; import android.widget.TextView;
import java.io.IOException;
public class AudioPlayer extends Activity implements OnPreparedListener, MediaController.MediaPlayerControl{ private static final String TAG = "AudioPlayer";
public static final String AUDIO_FILE_NAME = "audioFileName";
private MediaPlayer mediaPlayer; private MediaController mediaController; private String audioFile;
private Handler handler = new Handler();
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.audio_player);
audioFile = this.getIntent().getStringExtra(AUDIO_FILE_NAME);
((TextView)findViewById(R.id.now_playing_text)).setText(audioFile);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaController = new MediaController(this);
try {
mediaPlayer.setDataSource(audioFile);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
Log.e(TAG, "Could not open file " + audioFile + " for playback.", e);
}
}
#Override protected void onStop() { super.onStop(); mediaController.hide(); mediaPlayer.stop(); mediaPlayer.release(); }
#Override public boolean onTouchEvent(MotionEvent event) { //the MediaController will hide after 3 seconds - tap the screen to make it appear again mediaController.show(); return false; }
//--MediaPlayerControl methods---------------------------------------------------- public void start() { mediaPlayer.start(); }
public void pause() { mediaPlayer.pause(); }
public int getDuration() { return mediaPlayer.getDuration(); }
public int getCurrentPosition() { return mediaPlayer.getCurrentPosition(); }
public void seekTo(int i) { mediaPlayer.seekTo(i); }
public boolean isPlaying() { return mediaPlayer.isPlaying(); }
public int getBufferPercentage() { return 0; }
public boolean canPause() { return true; }
public boolean canSeekBackward() { return true; }
public boolean canSeekForward() { return true; } //--------------------------------------------------------------------------------
public void onPrepared(MediaPlayer mediaPlayer) { Log.d(TAG, "onPrepared"); mediaController.setMediaPlayer(this); mediaController.setAnchorView(findViewById(R.id.main_audio_view));
handler.post(new Runnable() {
public void run() {
mediaController.setEnabled(true);
mediaController.show();
}
});
} }
XML file-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_audio_view" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_gravity="center"
android:orientation="vertical"> <TextView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:text="Now playing:"
android:textSize="25sp" android:textStyle="bold" /> <TextView
android:id="#+id/now_playing_text" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_marginTop="20dip"
android:layout_marginLeft="10dip" android:layout_marginRight="10dip"
android:layout_gravity="center" android:text="Now playing.."
android:textSize="16sp" android:textStyle="italic" /> </LinearLayout>
I had to tweak Patrick's solution a bit to play the file from assets folder but it worked great, here is reformatted java file for easy cut and paste if anyone needs it.
import android.content.res.AssetFileDescriptor;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.media.MediaPlayer.OnPreparedListener;
import android.view.MotionEvent;
import android.widget.MediaController;
import android.widget.TextView;
import java.io.IOException;
public class MediaPlayer extends AppCompatActivity implements OnPreparedListener, MediaController.MediaPlayerControl {
private static final String TAG = "AudioPlayer";
private android.media.MediaPlayer mediaPlayer;
private MediaController mediaController;
private String audioFileName = "item1_audio1.mp3";;
private Handler handler = new Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_audio_view);
((TextView) findViewById(R.id.now_playing_text)).setText(audioFileName);
mediaPlayer = new android.media.MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaController = new MediaController(this);
try {
AssetFileDescriptor descriptor = MediaPlayer.this.getAssets().openFd(audioFileName);
long start = descriptor.getStartOffset();
long end = descriptor.getLength();
mediaPlayer.setDataSource(descriptor.getFileDescriptor(), start, end);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
Log.e(TAG, "Could not open file " + audioFileName + " for playback.", e);
}
}
#Override
public void onPrepared(android.media.MediaPlayer mp) {
Log.d(TAG, "onPrepared");
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(findViewById(R.id.main_audio_view));
handler.post(new Runnable() {
public void run() {
mediaController.setEnabled(true);
mediaController.show();
}
});
}
#Override
protected void onStop() {
super.onStop();
mediaController.hide();
}
#Override
public boolean onTouchEvent(MotionEvent event) { //the MediaController will hide after 3 seconds - tap the screen to make it appear again
mediaController.show();
return false;
}
public void start() {
mediaPlayer.start();
}
public void pause() {
mediaPlayer.pause();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public void seekTo(int i) {
mediaPlayer.seekTo(i);
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public int getBufferPercentage() {
return 0;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
#Override
public void onStart() {
super.onStart();
}
}
I'm not very experienced in Android, but I'm trying to make a Media Playback Service. My Start and Stop are working, but Pause/Play aren't. I've tried many different ways, but always unsuccessful.
When I pause and press play again, it starts from 0 or give me an error:
11-02 18:50:57.971 2043-2043/? E/MediaPlayer﹕ start called in state 2
11-02 18:50:57.971 2043-2043/? E/MediaPlayer﹕ error (-38, 0)
11-02 18:50:57.975 2043-2043/? E/MediaPlayer﹕ Error (-38,0)
Here is my Main Activity:
package my.package;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
Button btnStartSvc;
Button btnStopSvc;
Button btnPauseSvc;
Button btnResumeSvc;
private static final String TAG = "MyService";
private static final String TAG_LINK = "link";
private static final String TAG_PAUSE = "PAUSE";
private static final String TAG_STOP = "STOP";
private static final String TAG_ACTION = "ACTION";
private String pause = "pause";
private String stop = "stop";
private String link;
Context context;
boolean playPause;
private boolean initialStage = true;
MediaPlayer mediaPlayer = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStartSvc = (Button) findViewById(R.id.btnStartSvc);
btnStopSvc = (Button) findViewById(R.id.btnStopSvc);
btnPauseSvc = (Button) findViewById(R.id.btnPauseSvc);
btnResumeSvc = (Button) findViewById(R.id.btnResumeSvc);
link = "http://stats.jovemnerd.com.br/nc489alta.mp3";
context = this;
mediaPlayer = new MediaPlayer();
btnStartSvc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startSvc();
}
});
btnStopSvc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopSvc();
}
});
btnPauseSvc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pauseSvc();
}
});
btnResumeSvc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
resumeSvc();
}
});
}
public void resumeSvc(){
Intent i = new Intent(this,MyService.class);
i.putExtra("action", "my.package.action.RESUME");
startService(i);
}
public void pauseSvc(){
Intent i = new Intent(this,MyService.class);
i.putExtra("action", "my.package.action.PAUSE");
startService(i);
}
public void startSvc(){
Log.d(TAG, "Start");
Intent i = new Intent(this, MyService.class);
i.putExtra("action", "my.package.action.PLAY");
i.putExtra(TAG_LINK, link);
startService(i);
}
public void stopSvc(){
initialStage = true;
playPause=false;
Log.d(TAG, "Stop");
Intent i = new Intent(this, MyService.class);
stopService(i);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Service:
package my.package;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.wifi.WifiManager;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;
import java.io.IOException;
import java.net.URISyntaxException;
public class MyService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener {
private static final String ACTION_PLAY = "my.package.action.PLAY";
private static final String ACTION_PAUSE = "my.package.action.PAUSE";
private static final String ACTION_STOP = "my.package.action.STOP";
private static final String ACTION_RESUME = "my.package.action.RESUME";
private static final String TAG = "MyService";
private static final String TAG_LINK = "link";
private static final String TAG_PAUSE = "PAUSE";
private static final String TAG_STOP = "STOP";
private static final String TAG_ACTION = "ACTION";
private String url = "";
private String teste = "http://stats.jovemnerd.com.br/nc489alta.mp3";
private String action;
MediaPlayer mediaPlayer = null;
WifiManager.WifiLock wifiLock;
boolean playPause;
private boolean initialStage = true;
public MyService() {
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
teste = intent.getStringExtra("action");
Log.d("Work: ", teste);
if (intent.getStringExtra("action").equals(ACTION_PLAY)) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
url = intent.getStringExtra(TAG_LINK);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(this);
try {
mediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
if (!playPause) {
//btnPlayPause.setImageResource(R.drawable.ic_pause_white);
if (initialStage) {
Log.d("PLAY", "PLAY");
mediaPlayer.prepareAsync();
wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();
} else if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
//seekBar.setMax((int) finalTime);
}
playPause = true;
initialStage = false;
}
} else if (intent.getStringExtra("action").equals(ACTION_PAUSE)){
Log.d("PAUSE", "PAUSE");
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
if(mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.release();
}
playPause = false;
initialStage = false;
mediaPlayer = null;
}
} /*else if (intent.getStringExtra("action").equals(ACTION_RESUME)){
if (!mediaPlayer.isPlaying())
mediaPlayer.start();
}*/
//url = intent.getStringExtra(TAG_LINK);
/*mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);*/
Log.d(TAG, "Start Command");
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "Player Started");
mediaPlayer.start();
initialStage = false;
}
#Override
public void onCompletion(MediaPlayer mp) {
Log.d("Completed: ", "ok");
}
#Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
mediaPlayer.release();
Log.d(TAG, "Stop Command" + action);
}
wifiLock.release();
initialStage = true;
playPause = false;
}
public void pausePlayer(){
if(mediaPlayer != null){
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Manifest:
<service
android:name="my.package.MyService"
android:enabled="true"
android:exported="true" >
</service>
*Service is inside <Application>
I hope you can help me. Thx.
I want a service which runs a CountDownTimer and in every tick I want to show the countdown in a Activity and after some interval play a sound.
All the process are going fine in a single Activity but during incoming call the countdown not working that's why I want to do this using a Service.
Can anybody help me?
thanks in advance.
Update...
mCountDownTimer = new CountDownTimer(mTimerDuration, 1000) {
#Override
public void onTick(long millisUntilFinished) {
if (mTimerDuration > 0) {
mDurationCount += 1000;
showCountDown(
ActivityA.this,
(mSimpleDateFormat.format(mTimerDuration
- mDurationCount)));
if (mDurationCount == mTimerDuration) {
if (mRepeatTime > 1) {
startRepeatTimer();
}
finishTimer();
}
}
}
#Override
public void onFinish() {
}
}.start();
The easiest way is probably to create a broadcast receiver in your activity and have the service send broadcasts to the receiver. Here's a full listing for a service class with a simplified CountDownTimer.
package com.example.cdt;
import android.app.Service;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.util.Log;
public class BroadcastService extends Service {
private final static String TAG = "BroadcastService";
public static final String COUNTDOWN_BR = "your_package_name.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Starting timer...");
cdt = new CountDownTimer(30000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
bi.putExtra("countdown", millisUntilFinished);
sendBroadcast(bi);
}
#Override
public void onFinish() {
Log.i(TAG, "Timer finished");
}
};
cdt.start();
}
#Override
public void onDestroy() {
cdt.cancel();
Log.i(TAG, "Timer cancelled");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
And here are the relevant lines from a main activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService(new Intent(this, BroadcastService.class));
Log.i(TAG, "Started service");
}
private BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateGUI(intent); // or whatever method used to update your GUI fields
}
};
#Override
public void onResume() {
super.onResume();
registerReceiver(br, new IntentFilter(BroadcastService.COUNTDOWN_BR));
Log.i(TAG, "Registered broacast receiver");
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(br);
Log.i(TAG, "Unregistered broacast receiver");
}
#Override
public void onStop() {
try {
unregisterReceiver(br);
} catch (Exception e) {
// Receiver was probably already stopped in onPause()
}
super.onStop();
}
#Override
public void onDestroy() {
stopService(new Intent(this, BroadcastService.class));
Log.i(TAG, "Stopped service");
super.onDestroy();
}
private void updateGUI(Intent intent) {
if (intent.getExtras() != null) {
long millisUntilFinished = intent.getLongExtra("countdown", 0);
Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished / 1000);
}
}
You'll also need to define the service between the start/end application tags in your manifest file.
<service android:name=".BroadcastService" />
Download source code Android Countdown Timer Run In Background
activity_main.xml
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/et_hours"
android:hint="Hours"
android:inputType="time"
android:layout_marginRight="5dp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btn_timer"
android:layout_above="#+id/btn_cancel"
android:text="Start Timer"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:id="#+id/btn_cancel"
android:text="cancel timer"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tv_timer"
android:layout_centerInParent="true"
android:textSize="25dp"
android:textColor="#000000"
android:text="00:00:00"/>
</RelativeLayout>
Timer_Service.java
package com.countdowntimerservice;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
public class Timer_Service extends Service {
public static String str_receiver = "com.countdowntimerservice.receiver";
private Handler mHandler = new Handler();
Calendar calendar;
SimpleDateFormat simpleDateFormat;
String strDate;
Date date_current, date_diff;
SharedPreferences mpref;
SharedPreferences.Editor mEditor;
private Timer mTimer = null;
public static final long NOTIFY_INTERVAL = 1000;
Intent intent;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mEditor = mpref.edit();
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);
intent = new Intent(str_receiver);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
strDate = simpleDateFormat.format(calendar.getTime());
Log.e("strDate", strDate);
twoDatesBetweenTime();
}
});
}
}
public String twoDatesBetweenTime() {
try {
date_current = simpleDateFormat.parse(strDate);
} catch (Exception e) {
}
try {
date_diff = simpleDateFormat.parse(mpref.getString("data", ""));
} catch (Exception e) {
}
try {
long diff = date_current.getTime() - date_diff.getTime();
int int_hours = Integer.valueOf(mpref.getString("hours", ""));
long int_timer = TimeUnit.HOURS.toMillis(int_hours);
long long_hours = int_timer - diff;
long diffSeconds2 = long_hours / 1000 % 60;
long diffMinutes2 = long_hours / (60 * 1000) % 60;
long diffHours2 = long_hours / (60 * 60 * 1000) % 24;
if (long_hours > 0) {
String str_testing = diffHours2 + ":" + diffMinutes2 + ":" + diffSeconds2;
Log.e("TIME", str_testing);
fn_update(str_testing);
} else {
mEditor.putBoolean("finish", true).commit();
mTimer.cancel();
}
}catch (Exception e){
mTimer.cancel();
mTimer.purge();
}
return "";
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("Service finish","Finish");
}
private void fn_update(String str_time){
intent.putExtra("time",str_time);
sendBroadcast(intent);
}
}
MainActivity.java
package com.countdowntimerservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_start, btn_cancel;
private TextView tv_timer;
String date_time;
Calendar calendar;
SimpleDateFormat simpleDateFormat;
EditText et_hours;
SharedPreferences mpref;
SharedPreferences.Editor mEditor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
listener();
}
private void init() {
btn_start = (Button) findViewById(R.id.btn_timer);
tv_timer = (TextView) findViewById(R.id.tv_timer);
et_hours = (EditText) findViewById(R.id.et_hours);
btn_cancel = (Button) findViewById(R.id.btn_cancel);
mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mEditor = mpref.edit();
try {
String str_value = mpref.getString("data", "");
if (str_value.matches("")) {
et_hours.setEnabled(true);
btn_start.setEnabled(true);
tv_timer.setText("");
} else {
if (mpref.getBoolean("finish", false)) {
et_hours.setEnabled(true);
btn_start.setEnabled(true);
tv_timer.setText("");
} else {
et_hours.setEnabled(false);
btn_start.setEnabled(false);
tv_timer.setText(str_value);
}
}
} catch (Exception e) {
}
}
private void listener() {
btn_start.setOnClickListener(this);
btn_cancel.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_timer:
if (et_hours.getText().toString().length() > 0) {
int int_hours = Integer.valueOf(et_hours.getText().toString());
if (int_hours<=24) {
et_hours.setEnabled(false);
btn_start.setEnabled(false);
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
date_time = simpleDateFormat.format(calendar.getTime());
mEditor.putString("data", date_time).commit();
mEditor.putString("hours", et_hours.getText().toString()).commit();
Intent intent_service = new Intent(getApplicationContext(), Timer_Service.class);
startService(intent_service);
}else {
Toast.makeText(getApplicationContext(),"Please select the value below 24 hours",Toast.LENGTH_SHORT).show();
}
/*
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);*/
} else {
Toast.makeText(getApplicationContext(), "Please select value", Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_cancel:
Intent intent = new Intent(getApplicationContext(),Timer_Service.class);
stopService(intent);
mEditor.clear().commit();
et_hours.setEnabled(true);
btn_start.setEnabled(true);
tv_timer.setText("");
break;
}
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String str_time = intent.getStringExtra("time");
tv_timer.setText(str_time);
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(broadcastReceiver,new IntentFilter(Timer_Service.str_receiver));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
}
I'm developing an Android Application to a college work. In this work I want to create a background service with a timer and when I close the application, timer still running. When I open the app, I can see the time since I've started service.
Well, my problem is that when I close the app, the background timer stops and not increments more.
Can you help me please?
Thanks a lot
My launcher class
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button startButton;
private Button pauseButton;
private TextView timerValue;
Intent intent;
long timeSwapBuff = 0L;
long updatedTime = 0L;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
timerValue = (TextView) findViewById(R.id.timerValue);
startButton = (Button) findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
intent = new Intent(MainActivity.this, CounterService.class);
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(CounterService.BROADCAST_ACTION));
}
});
pauseButton = (Button) findViewById(R.id.pauseButton);
pauseButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
unregisterReceiver(broadcastReceiver);
stopService(intent);
}
});
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
private void updateUI(Intent intent) {
int time = intent.getIntExtra("time", 0);
Log.d("Hello", "Time " + time);
int mins = time / 60;
int secs = time % 60;
timerValue.setText("" + mins + ":"
+ String.format("%02d", secs));
}
}
and here, the service class
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
public class CounterService extends Service {
private Intent intent;
public static final String BROADCAST_ACTION = "com.javacodegeeks.android.androidtimerexample.MainActivity";
private Handler handler = new Handler();
private long initial_time;
long timeInMilliseconds = 0L;
#Override
public void onCreate() {
super.onCreate();
initial_time = SystemClock.uptimeMillis();
intent = new Intent(BROADCAST_ACTION);
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 1000); // 1 seconds
}
};
private void DisplayLoggingInfo() {
timeInMilliseconds = SystemClock.uptimeMillis() - initial_time;
int timer = (int) timeInMilliseconds / 1000;
intent.putExtra("time", timer);
sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendUpdatesToUI);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
you need to start your service in the onStop() method in your activity like this:
#Override
protected void onStop() {
super.onStop();
//write your code here to start your service
}
Kindly go through the link hope it will be helpful if you want to run timer in background Timer in background
activity_main.xml
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/et_hours"
android:hint="Hours"
android:inputType="time"
android:layout_marginRight="5dp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btn_timer"
android:layout_above="#+id/btn_cancel"
android:text="Start Timer"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:id="#+id/btn_cancel"
android:text="cancel timer"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tv_timer"
android:layout_centerInParent="true"
android:textSize="25dp"
android:textColor="#000000"
android:text="00:00:00"/>
</RelativeLayout>
MainActivity.java
package playstore.com.a02backgroundtimer;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_start, btn_cancel;
private TextView tv_timer;
String date_time;
Calendar calendar;
SimpleDateFormat simpleDateFormat;
EditText et_hours;
SharedPreferences mpref;
SharedPreferences.Editor mEditor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
listener();
}
private void init() {
btn_start = (Button) findViewById(R.id.btn_timer);
tv_timer = (TextView) findViewById(R.id.tv_timer);
et_hours = (EditText) findViewById(R.id.et_hours);
btn_cancel = (Button) findViewById(R.id.btn_cancel);
mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mEditor = mpref.edit();
try {
String str_value = mpref.getString("data", "");
if (str_value.matches("")) {
et_hours.setEnabled(true);
btn_start.setEnabled(true);
tv_timer.setText("");
} else {
if (mpref.getBoolean("finish", false)) {
et_hours.setEnabled(true);
btn_start.setEnabled(true);
tv_timer.setText("");
} else {
et_hours.setEnabled(false);
btn_start.setEnabled(false);
tv_timer.setText(str_value);
}
}
} catch (Exception e) {
}
}
private void listener() {
btn_start.setOnClickListener(this);
btn_cancel.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_timer:
if (et_hours.getText().toString().length() > 0) {
int int_hours = Integer.valueOf(et_hours.getText().toString());
if (int_hours<=24) {
et_hours.setEnabled(false);
btn_start.setEnabled(false);
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
date_time = simpleDateFormat.format(calendar.getTime());
mEditor.putString("data", date_time).commit();
mEditor.putString("hours", et_hours.getText().toString()).commit();
Intent intent_service = new Intent(getApplicationContext(), Timer_Service.class);
startService(intent_service);
}else {
Toast.makeText(getApplicationContext(),"Please select the value below 24 hours",Toast.LENGTH_SHORT).show();
}
/*
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);*/
} else {
Toast.makeText(getApplicationContext(), "Please select value", Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_cancel:
Intent intent = new Intent(getApplicationContext(),Timer_Service.class);
stopService(intent);
mEditor.clear().commit();
et_hours.setEnabled(true);
btn_start.setEnabled(true);
tv_timer.setText("");
break;
}
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String str_time = intent.getStringExtra("time");
tv_timer.setText(str_time);
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(broadcastReceiver,new IntentFilter(Timer_Service.str_receiver));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
}
Timer_Service.java
package playstore.com.a02backgroundtimer;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
public class Timer_Service extends Service {
public static String str_receiver = "com.countdowntimerservice.receiver";
private Handler mHandler = new Handler();
Calendar calendar;
SimpleDateFormat simpleDateFormat;
String strDate;
Date date_current, date_diff;
SharedPreferences mpref;
SharedPreferences.Editor mEditor;
private Timer mTimer = null;
public static final long NOTIFY_INTERVAL = 1000;
Intent intent;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mEditor = mpref.edit();
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);
intent = new Intent(str_receiver);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
strDate = simpleDateFormat.format(calendar.getTime());
Log.e("strDate", strDate);
twoDatesBetweenTime();
}
});
}
}
public String twoDatesBetweenTime() {
try {
date_current = simpleDateFormat.parse(strDate);
} catch (Exception e) {
}
try {
date_diff = simpleDateFormat.parse(mpref.getString("data",""));
} catch (Exception e) {
}
try {
long diff = date_current.getTime() - date_diff.getTime();
int int_hours = Integer.valueOf(mpref.getString("hours", ""));
long int_timer = TimeUnit.HOURS.toMillis(int_hours);
long long_hours = int_timer - diff;
long diffSeconds2 = long_hours / 1000 % 60;
long diffMinutes2 = long_hours / (60 * 1000) % 60;
long diffHours2 = long_hours / (60 * 60 * 1000) % 24;
if (long_hours > 0) {
String str_testing = diffHours2 + ":" + diffMinutes2 + ":" + diffSeconds2;
Log.e("TIME", str_testing);
fn_update(str_testing);
} else {
mEditor.putBoolean("finish", true).commit();
mTimer.cancel();
}
} catch (Exception e) {
mTimer.cancel();
mTimer.purge();
}
return "";
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("Service finish", "Finish");
}
private void fn_update(String str_time) {
intent.putExtra("time", str_time);
sendBroadcast(intent);
}
}
Once the app starts you need to mention the hours you want timer for ... Then also after killing the app when you restarts the app it will show the start time of the timer ... Now you customize you application a per your requirement .
I want to develop a simple stop watch logic in android.
On clicking a list view the timer should start and on clicking the button the timer should stop. Can anyone please guide me. Any sample code will be of great help
Use the Stopwatch Class (For higher precision use System.nanoTime())
Add a Start() event and Stop() event on Button Presses. You'll need to update the UI so use a Thread/Handler Combination.
This should get you started.
EDIT: Added Code. (Nice Exercise! :) )
Use the Refresh_Rate to configure how often your UI is updated.
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Main extends Activity implements OnClickListener{
final int MSG_START_TIMER = 0;
final int MSG_STOP_TIMER = 1;
final int MSG_UPDATE_TIMER = 2;
Stopwatch timer = new Stopwatch();
final int REFRESH_RATE = 100;
Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_START_TIMER:
timer.start(); //start timer
mHandler.sendEmptyMessage(MSG_UPDATE_TIMER);
break;
case MSG_UPDATE_TIMER:
tvTextView.setText(""+ timer.getElapsedTime());
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE); //text view is updated every second,
break; //though the timer is still running
case MSG_STOP_TIMER:
mHandler.removeMessages(MSG_UPDATE_TIMER); // no more updates.
timer.stop();//stop timer
tvTextView.setText(""+ timer.getElapsedTime());
break;
default:
break;
}
}
};
TextView tvTextView;
Button btnStart,btnStop;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvTextView = (TextView)findViewById(R.id.TextView01);
btnStart = (Button)findViewById(R.id.Button01);
btnStop= (Button)findViewById(R.id.Button02);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
}
public void onClick(View v) {
if(btnStart == v)
{
mHandler.sendEmptyMessage(MSG_START_TIMER);
}else
if(btnStop == v){
mHandler.sendEmptyMessage(MSG_STOP_TIMER);
}
}
}
As st0le gave an excellent example by using Stopwatch class. I modified this class a little and add a few methods to it.
/*
Copyright (c) 2005, Corey Goldberg
StopWatch.java is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Modified: Bilal Rabbani bilalrabbani1#live.com (Nov 2013)
*/
package bilalrabbani1.at.live.com;
public class Stopwatch {
private long startTime = 0;
private boolean running = false;
private long currentTime = 0;
public void start() {
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop() {
this.running = false;
}
public void pause() {
this.running = false;
currentTime = System.currentTimeMillis() - startTime;
}
public void resume() {
this.running = true;
this.startTime = System.currentTimeMillis() - currentTime;
}
//elaspsed time in milliseconds
public long getElapsedTimeMili() {
long elapsed = 0;
if (running) {
elapsed =((System.currentTimeMillis() - startTime)/100) % 1000 ;
}
return elapsed;
}
//elaspsed time in seconds
public long getElapsedTimeSecs() {
long elapsed = 0;
if (running) {
elapsed = ((System.currentTimeMillis() - startTime) / 1000) % 60;
}
return elapsed;
}
//elaspsed time in minutes
public long getElapsedTimeMin() {
long elapsed = 0;
if (running) {
elapsed = (((System.currentTimeMillis() - startTime) / 1000) / 60 ) % 60;
}
return elapsed;
}
//elaspsed time in hours
public long getElapsedTimeHour() {
long elapsed = 0;
if (running) {
elapsed = ((((System.currentTimeMillis() - startTime) / 1000) / 60 ) / 60);
}
return elapsed;
}
public String toString() {
return getElapsedTimeHour() + ":" + getElapsedTimeMin() + ":"
+ getElapsedTimeSecs() + "." + getElapsedTimeMili();
}
}
Regards
Instead of using listview you simply use a text view for timer and 3 buttons for stop start and reset . Using these you can make the java code accordingly
Good example, just in case if someone wants that layout file to go with this (pretty simple though).
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<EditText
android:id="#+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView1"
android:layout_below="#+id/textView1"
android:layout_marginLeft="18dp"
android:layout_marginTop="49dp"
android:ems="10" >
<requestFocus />
</EditText>
<Button
android:id="#+id/Button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/TextView01"
android:layout_marginTop="42dp"
android:layout_toRightOf="#+id/textView1"
android:text="Start" />
<Button
android:id="#+id/Button02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/Button01"
android:layout_marginTop="14dp"
android:layout_toRightOf="#+id/textView1"
android:text="Stop" />
IntentService based, no non-SDK dependencies and on a single file:
import android.app.Activity;
import android.app.IntentService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class Main extends Activity {
static final String BROADCAST_ACTION = "com.cirosantilli.android_cheat.intent_service_text_view.BROADCAST";
static final String EXTENDED_DATA_STATUS = "com.cirosantilli.android_cheat.intent_service_text_view.BROADCAST";
static final String TAG = "com.cirosantilli";
private int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
final LinearLayout linearLayout = new LinearLayout(this);
Button button;
final Intent intent = new Intent(Main.this, MyService.class);
button = new Button(this);
button.setText("start service");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "start button");
Main.this.startService(intent.putExtra(Main.EXTENDED_DATA_STATUS, Main.this.i));
}
});
linearLayout.addView(button);
button = new Button(this);
button.setText("stop service");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "stop button");
Main.this.stopService(intent);
}
});
linearLayout.addView(button);
final TextView textView = new TextView(this);
textView.setText(Integer.toString(i));
linearLayout.addView(textView);
this.setContentView(linearLayout);
LocalBroadcastManager.getInstance(this).registerReceiver(
new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Main.this.i = intent.getIntExtra(Main.EXTENDED_DATA_STATUS, 0);
textView.setText(Integer.toString(Main.this.i));
}
}, new IntentFilter(Main.BROADCAST_ACTION)
);
}
public static class MyService extends IntentService {
private Handler mHandler;
private int i = 1;
private boolean done;
public MyService() {
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent");
this.i = intent.getIntExtra(Main.EXTENDED_DATA_STATUS, 0);
this.done = false;
while(!done) {
Log.d(TAG, "while true");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
LocalBroadcastManager.getInstance(this).sendBroadcast(
new Intent(Main.BROADCAST_ACTION)
.putExtra(Main.EXTENDED_DATA_STATUS, MyService.this.i));
this.i++;
}
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
this.done = true;
super.onDestroy();
}
}
}
For low precision only. We could get increased precision by using System.currentTimeMillis inside onHandleIntent instead of using the integer value, and reducing the sleep time to reduce latency.
Tested on Android 22. Standard build boilerplate here.