i have used the android:stopWithTask="false" but it never work with one of my services
<service android:name=".EcaService"
android:enabled="true"
android:stopWithTask="false"/>
and the service is:
package com.example.ayham.usefullalarm;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.IBinder;
import android.util.Log;
/**
* Created by ayham on 7/8/2017.
*/
public class EcaService extends Service {
private BroadcastReceiver batteryReceiver;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
registerBatteryReceiver();
}
private void registerBatteryReceiver() {
batteryReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (MainView.eca_activeCode < 1) {
// How are we charging?
Log.e("in first if", ": done");
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean wirelessCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_WIRELESS;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
if (acCharge || wirelessCharge) {
Log.e("in second if", ": done");
Intent do_Alarm = new Intent(context, BatteryAlarmView.class);
do_Alarm.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainView.eca_activeCode++;
context.startActivity(do_Alarm);
}
}
}
};
IntentFilter electricalAIntent = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryReceiver, electricalAIntent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("in the receiver","yay");
/*Intent doAlarm = new Intent(this, BatteryAlarmView.class);
doAlarm.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(doAlarm);*/
return START_NOT_STICKY;
}
}
in the MainView the code is:
public class MainView extends Activity {
static int eca_activeCode = 0;
Button eca;
Intent eca_intent;
boolean eca_s;
/*#Override
public void onBackPressed() {
Intent itent = new Intent(this, MainView.class);
startActivity(itent);
}*/
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
moveTaskToBack(true);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main_view);
this.context = this;
//to be used in decision of the eca
eca_s = false;
//initialize the eca button
eca = (Button)findViewById(R.id.e_status);
//initialize the textView related to the eca
ecaText = (TextView)findViewById(R.id.EText);
//add a click listener to the eca button to start the electrical alarm
eca.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//decide whether to activate or not
String s ;
if(!eca_s) {
eca_activeCode = 0;
eca_s = true;
s = "ON";
eca_intent = new Intent(context,EcaService.class);
context.startService(eca_intent);
}
else {
eca_s =false;
s = "Off";
eca_intent = new Intent(context,EcaService.class);
context.stopService(eca_intent);
}
//set the button text to indicate the status of eca
eca.setText(s);
}
});
//receive the battery alarm intent
if(eca_intent != null) {
Intent b_back = getIntent();
eca_s = false;
String s = "Off";
String class_name = b_back.getExtras().getString("Class");
if (class_name.equalsIgnoreCase("BatteryAlarmView")) {
eca_intent = new Intent(context,EcaService.class);
context.stopService(eca_intent);
eca_activeCode = 0;
//set the button text to indicate the status of eca
eca.setText(s);
}
}
}
}
what is wrong with the code, it did not give any error!!
Related
I am creating a separate thread in a android bounded service's onStartCommand() and running it using a condition check in Runnable's Run() e.g. while (condition), there is a activity which is using this bounded service and then unbound it. I read that there is a rule that bounded services automatically destroyed if there is no activity bound to it. Do I need to flip my condition in unbind method otherwise how service will know that it must terminate now ? If yes, then its controlled by my code not by Android itself
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class ServiceDemo extends Service {
private static final String TAG = "ServiceDemo";
private boolean isRunning = false;
private boolean isBound = false;
private int counter = 0;
private static final int MIN = 0;
private static final int MAX = 100;
IBinder myServiceBinder = new MyServiceBinder();
public class MyServiceBinder extends Binder {
public ServiceDemo getServiceInstance(){
return ServiceDemo.this;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
isBound = true;
return myServiceBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand executed in Thread : "+Thread.currentThread().getId());
isRunning = true;
generateSequentialInteger(MIN, MAX);
return START_NOT_STICKY;
}
private void generateSequentialInteger(int start, int stop){
new Thread(new Runnable() {
#Override
public void run() {
counter = start;
while(isRunning && counter<stop){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, "Thread ID : "+Thread.currentThread().getId()+" : Service has generated number "+counter);
counter++;
}
}
}).start();
}
#Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind executed");
isBound = false;
return super.onUnbind(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
isRunning = false;
Log.i(TAG, "onDestroy executed");
}
}
'''
Following [this tutorial] (http://www.tutorialsface.com/2015/08/android-custom-notification-tutorial) I ended up with the controls showing in the notification, but all are unresponsive (other than showing the Toasts the author included).
The controls don't seem to be bound to the music service in any way. I've tried creating a broadcast, calling the service directly from within the notifications, creating a new instance of the service. I've tried so many things I can't even remember all of them. I've seen people ask similar questions but nothing I've tried works. Now I've tried so many things that I've gotten myself confused about when/where I thought I was on a 'right path'. Any ideas as to how to get these controls functioning properly?
Notification Service:
public class NotificationService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constant.ACTION.STARTFOREGROUND_ACTION)) {
showNotification();
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
} else if (intent.getAction().equals(Constant.ACTION.PREV_ACTION)) {
Toast.makeText(this, "Clicked Previous", Toast.LENGTH_SHORT).show();
Log.i("NS", "Clicked Previous");
} else if (intent.getAction().equals(Constant.ACTION.PLAY_ACTION)) {
Log.i("NS", "Clicked Play");
} else if (intent.getAction().equals(Constant.ACTION.NEXT_ACTION)) {
Toast.makeText(this, "Clicked Next", Toast.LENGTH_SHORT).show();
Log.i("NS", "Clicked Next");
} else if (intent.getAction().equals(
Constant.ACTION.STOPFOREGROUND_ACTION)) {
Log.i("NS", "Received Stop Foreground Intent");
Toast.makeText(this, "Service Stoped", Toast.LENGTH_SHORT).show();
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void showNotification() {
Notification status;
// Using RemoteViews to bind custom layouts into Notification
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.status_bar);
RemoteViews bigViews = new RemoteViews(getPackageName(),
R.layout.status_bar_expanded);
// showing default album image
views.setViewVisibility(R.id.status_bar_icon, View.VISIBLE);
views.setViewVisibility(R.id.status_bar_album_art, View.GONE);
bigViews.setImageViewBitmap(R.id.status_bar_album_art,
Constant.getDefaultAlbumArt(this));
Intent notificationIntent = new Intent(this, NotificationService.class);
notificationIntent.setAction(Constant.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Intent previousIntent = new Intent(this, NotificationService.class);
previousIntent.setAction(Constant.ACTION.PREV_ACTION);
PendingIntent ppreviousIntent = PendingIntent.getService(this, 0,
previousIntent, 0);
Intent playIntent = new Intent(this, NotificationService.class);
playIntent.setAction(Constant.ACTION.PLAY_ACTION);
PendingIntent pplayIntent = PendingIntent.getService(this, 0,
playIntent, 0);
Intent nextIntent = new Intent(this, NotificationService.class);
nextIntent.setAction(Constant.ACTION.NEXT_ACTION);
PendingIntent pnextIntent = PendingIntent.getService(this, 0,
nextIntent, 0);
Intent closeIntent = new Intent(this, NotificationService.class);
closeIntent.setAction(Constant.ACTION.STOPFOREGROUND_ACTION);
PendingIntent pcloseIntent = PendingIntent.getService(this, 0,
closeIntent, 0);
views.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
views.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);
views.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);
views.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);
bigViews.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);
views.setImageViewResource(R.id.status_bar_play,
R.drawable.apollo_holo_dark_pause);
bigViews.setImageViewResource(R.id.status_bar_play,
R.drawable.apollo_holo_dark_pause);
views.setTextViewText(R.id.status_bar_track_name, "Song Title");
bigViews.setTextViewText(R.id.status_bar_track_name, "Song Title");
views.setTextViewText(R.id.status_bar_artist_name, "Artist Name");
bigViews.setTextViewText(R.id.status_bar_artist_name, "Artist Name");
bigViews.setTextViewText(R.id.status_bar_album_name, "Album Name");
status = new Notification.Builder(this).build();
status.contentView = views;
status.bigContentView = bigViews;
status.flags = Notification.FLAG_ONGOING_EVENT;
status.icon = R.drawable.ic_launcher;
status.contentIntent = pendingIntent;
startForeground(Constant.NOTIFICATION_ID.FOREGROUND_SERVICE, status);
}
}
MusicService:
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 final IBinder musicBind = new MusicBinder();
private String songTitle="";
private static final int NOTIFY_ID=1;
private boolean shuffle=false;
private Random rand;
public void onCreate(){
//create the service
super.onCreate();
songPosn=0;
player = new MediaPlayer();
initMusicPlayer();
rand=new Random();
}
public void initMusicPlayer(){
//set player properties
player.setWakeMode(getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
}
public void setList(ArrayList<Song> theSongs){
songs=theSongs;
}
public class MusicBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
public void setShuffle(){
if(shuffle) shuffle=false;
else shuffle=true;
}
public void playSong(){
player.reset();
//get song
Song playSong = songs.get(songPosn);
//get id
long currSong = playSong.getID();
//set uri
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();
songTitle=playSong.getTitle();
}
public void setSong(int songIndex){
songPosn=songIndex;
}
public int getPosn(){
return player.getCurrentPosition();
}
public int getDur(){
return player.getDuration();
}
public boolean isPng(){
return player.isPlaying();
}
public void pausePlayer(){
player.pause();
}
public void seek(int posn){
player.seekTo(posn);
}
public void go(){
player.start();
}
public void playPrev(){
songPosn--;
if(songPosn<0) songPosn=songs.size()-1;
playSong();
}
//skip to next
public void playNext(){
if(shuffle){
int newSong = songPosn;
while(newSong==songPosn){
newSong=rand.nextInt(songs.size());
}
songPosn=newSong;
}
else{
songPosn++;
if(songPosn>=songs.size()) songPosn=0;
}
playSong();
}
#Override
public void onDestroy() {
stopForeground(true);
}
#Override
public IBinder onBind(Intent intent) {
return musicBind;
}
#Override
public boolean onUnbind(Intent intent){
player.stop();
player.release();
return false;
}
#Override
public void onCompletion(MediaPlayer mp) {
if(player.getCurrentPosition()>0){
mp.reset();
playNext();
}
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.reset();
return false;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onPrepared(MediaPlayer mp) {
//start playback
mp.start();
Intent onPreparedIntent = new Intent("MEDIA_PLAYER_PREPARED");
LocalBroadcastManager.getInstance(this).sendBroadcast(onPreparedIntent);
Intent notIntent = new Intent(this, MusicPlayer.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendInt = PendingIntent.getActivity(this, 0,
notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pendInt)
.setSmallIcon(R.drawable.player_play)
.setTicker(songTitle)
.setOngoing(true)
.setContentTitle("Playing")
.setContentText(songTitle);
Notification not = builder.build();
Intent serviceIntent = new Intent(MusicService.this, NotificationService.class);
serviceIntent.setAction(Constant.ACTION.STARTFOREGROUND_ACTION);
startService(serviceIntent);
}
}
Music Player:
public class MusicPlayer extends AppCompatActivity implements MediaPlayerControl {
private ArrayList<Song> songList;
private ListView songView;
public MusicService musicSrv;
private Intent playIntent;
private boolean musicBound=false;
private MusicController controller;
private boolean paused=false, playbackPaused=false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_player);
songView = (ListView)findViewById(R.id.song_list);
songList = new ArrayList<Song>();
getSongList();
Collections.sort(songList, new Comparator<Song>(){
public int compare(Song a, Song b){
return a.getArtist().compareTo(b.getArtist());
}
});
songAdapter songAdt = new songAdapter(this, songList);
songView.setAdapter(songAdt);
setController();
FloatingActionButton fabRandom = (FloatingActionButton)findViewById(R.id.fabRandom);
fabRandom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
//play next
private void playNext(){
musicSrv.playNext();
if(playbackPaused){
setController();
playbackPaused=false;
}
controller.show(0);
}
private void playPrev(){
musicSrv.playPrev();
if(playbackPaused){
setController();
playbackPaused=false;
}
controller.show(0);
}
public void songPicked(View view){
musicSrv.setSong(Integer.parseInt(view.getTag().toString()));
musicSrv.playSong();
if(playbackPaused){
setController();
playbackPaused=false;
}
setController();
controller.show(0);
}
#Override
protected void onPause(){
super.onPause();
paused=true;
}
#Override
protected void onResume(){
super.onResume();
// Set up receiver for media player onPrepared broadcast
LocalBroadcastManager.getInstance(this).registerReceiver(onPrepareReceiver,
new IntentFilter("MEDIA_PLAYER_PREPARED"));
if(paused){
setController();
paused=false;
}
}
#Override
protected void onStop() {
super.onStop();
}
private void setController(){
//set the controller up
if (controller == null) controller = new MusicController(this);
controller.invalidate();
controller.setPrevNextListeners(new View.OnClickListener() {
#Override
public void onClick(View v) {
playNext();
}
}, new View.OnClickListener() {
#Override
public void onClick(View v) {
playPrev();
}
});
controller.setMediaPlayer(this);
controller.setAnchorView(findViewById(R.id.song_list));
}
#Override
public void onBackPressed() {
moveTaskToBack(true);
Intent intent = new Intent (getApplicationContext(), FitnessActivity.class);
startActivity(intent);
}
// Broadcast receiver to determine when music player has been prepared
private BroadcastReceiver onPrepareReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent i) {
// When music player has been prepared, show controller
controller.show(0);
}
};
private BroadcastReceiver onNextClickedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
musicSrv.playNext();
}
};
//connect to the service
public ServiceConnection musicConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder binder = (MusicService.MusicBinder)service;
//get service
musicSrv = binder.getService();
//pass list
musicSrv.setList(songList);
musicBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
}
};
#Override
protected void onStart() {
super.onStart();
if(playIntent==null){
playIntent = new Intent(this, MusicService.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
setController();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_shuffle:
musicSrv.setShuffle();
break;
case R.id.action_end:
stopService(playIntent);
musicSrv=null;
System.exit(0);
break;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
stopService(playIntent);
musicSrv=null;
super.onDestroy();
}
public void getSongList() {
//retrieve song info
ContentResolver musicResolver = getContentResolver();
Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor musicCursor = musicResolver.query(musicUri, null, null, null, null);
if(musicCursor!=null && musicCursor.moveToFirst()){
//get columns
int titleColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.TITLE);
int idColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media._ID);
int artistColumn = musicCursor.getColumnIndex
(android.provider.MediaStore.Audio.Media.ARTIST);
int durationColumn = musicCursor.getColumnIndex
(MediaStore.Audio.Media.DURATION);
//add songs to list
do {
long thisId = musicCursor.getLong(idColumn);
String thisTitle = musicCursor.getString(titleColumn);
String thisArtist = musicCursor.getString(artistColumn);
long thisDuration = musicCursor.getLong(durationColumn);
if (thisDuration>10000){
songList.add(new Song(thisId, thisTitle, thisArtist, thisDuration));}
}
while (musicCursor.moveToNext());
}
}
#Override
public void start() {
musicSrv.go();
}
#Override
public void pause() {
playbackPaused=true;
musicSrv.pausePlayer();
}
#Override
public int getDuration() {
if(musicSrv!=null && musicBound && musicSrv.isPng())
return musicSrv.getDur();
else return 0;
}
#Override
public int getCurrentPosition() {
if(musicSrv!=null && musicBound && musicSrv.isPng())
return musicSrv.getPosn();
else return 0;
}
#Override
public void seekTo(int pos) {
musicSrv.seek(pos);
}
#Override
public boolean isPlaying() {
if(musicSrv!=null && musicBound)
return musicSrv.isPng();
return false;
}
#Override
public int getBufferPercentage() {
return 0;
}
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
public void onNextNotification(){
}
}
Manifest:
<activity
android:name=".MusicPlayer"
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MusicService"
/>
<service android:name=".NotificationService" />
Your notification actions gets received by Notifications service, not the Music service. Edit notification intents to target Music Service
Intent playIntent = new Intent(this, MusicService.class);
//... edit all of them
Move onStartCommand() method to Music Service and assign actions
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constant.ACTION.PLAY_ACTION)) {
//call play method
}
//...etc
except STARTFOREGROUND_ACTION and STOPFOREGROUND_ACTION, leave it in Notification Service's onStartCommand(). Also insert null check on Intent in both services.
I had created countdown timer to display timeout it works well when user minimize application but it stops when user close application. i had added code below kindly help me it's an emergency.
this is MainActivity.java
public static final String TAG = "Demo";
TextView t1 ;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t1 = (TextView)findViewById(R.id.t1);
startService(new Intent(this, count_servie.class));
}
private BroadcastReceiver br = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
updateGUI(intent);
}
};
public void onResume() {
super.onResume();
registerReceiver(br, new IntentFilter(count_servie.COUNTDOWN_BR));
}
private void updateGUI(Intent intent) {
if (intent.getExtras() != null) {
long millisUntilFinished = intent.getLongExtra("countdown", 0);
t1.setText("Countdown seconds remaining: " + millisUntilFinished / 1000);
}
}
this is my count_servie.java
public class count_servie extends Service {
public static final String COUNTDOWN_BR = "com.demo.DSemo.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
public void onCreate() {
super.onCreate();
cdt = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
bi.putExtra("countdown", millisUntilFinished);
sendBroadcast(bi);
}
public void onFinish() {
}
};
cdt.start();
}
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent arg0) {
return null;
}
Thanks in advance.
You need to return START_STCKY in your onStartCommand() method for the service to run even when app is closed.
....
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STCKY;
}
....
You can refer thislink for correctly implementing a service.
Alternatively, you can refer this SO question.
Update
Use a Foreground Service to avoid your Service being killed. In order to make your service Foreground, replace your onStartCommand code with this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Timer")
.setContentText("Doing some work...")
.setContentIntent(pendingIntent).build();
startForeground(1337, notification);
cdt = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
bi.putExtra("countdown", millisUntilFinished);
sendBroadcast(bi);
}
public void onFinish() {
stopForeground(true);
}
};
cdt.start();
return START_STICKY;
}
Udpate 2: Counter using Service and SharedPreferences
Replace your Actvity's code with this:
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.support.v4.os.ResultReceiver;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import java.util.Calendar;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String SHARED_PREF = "MyPref";
private final static int MAX_COUNTER = 30;
public static final String KEY_COUNTER_SECONDS = "seconds";
public static final String KEY_SAVED_COUNTER = "saved_counter";
public static final String KEY_SAVED_TIME_MILLI = "saved_time_milli";
MyResultReceiver mReceiver;
TextView mTvCounter;
SharedPreferences mSharedPref;
long mMaxCounterValueInSeconds = MAX_COUNTER;
long mCurCounterValue = 0;
boolean mShouldSaveValues;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTvCounter = (TextView) findViewById(R.id.tv_counter);
mReceiver = new MyResultReceiver(null);
mSharedPref = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
}
#Override
protected void onResume() {
super.onResume();
//register listener
MyService.registerReceiver(mReceiver);
//get values from shared pref
long savedCounter = mSharedPref.getLong(KEY_SAVED_COUNTER, -1);
long savedTime = mSharedPref.getLong(KEY_SAVED_TIME_MILLI, -1);
//if -1 counter was running when app was closed, get saved values from shared pref
if (savedTime != -1) {
//elapsedTime is the time spent in seconds while the app was in background
long elapsedTime = (getCurrentTimeInMilli() - savedTime)/1000; //convert to sec
mCurCounterValue = savedCounter + elapsedTime;
if(mCurCounterValue < MAX_COUNTER){
//calculate current counter value from values retrieved from shared pref
mMaxCounterValueInSeconds = MAX_COUNTER - mCurCounterValue;
//start the value with updated max count value
startService(mMaxCounterValueInSeconds);
}else{
mCurCounterValue = MAX_COUNTER;
}
}else{
//if counter was not running, start the service with max count value = MAX_COUNTER
startService(mMaxCounterValueInSeconds);
}
//update text view
mTvCounter.setText("" + mCurCounterValue);
}
private void startService(long maxCounter){
mShouldSaveValues = true;
Intent intent = new Intent(this, MyService.class);
Bundle bundle = new Bundle();
bundle.putLong(KEY_COUNTER_SECONDS, maxCounter);
intent.putExtras(bundle);
startService(intent);
}
#Override
protected void onPause() {
super.onPause();
//stop the service
stopService(new Intent(this, MyService.class));
//unregister listener
MyService.unregisterReceiver();
if(mShouldSaveValues) {//save the values only when counter has started
//save values in the shared preference
SharedPreferences.Editor editor = mSharedPref.edit();
Log.d(TAG, "saving counter: " + Long.parseLong(mTvCounter.getText().toString()));
editor.putLong(KEY_SAVED_COUNTER, Long.parseLong(mTvCounter.getText().toString()));
editor.putLong(KEY_SAVED_TIME_MILLI, getCurrentTimeInMilli());
editor.apply();
}
}
/**
* This method returns current time in milli seconds
*
* #return time in milliseconds
*/
private long getCurrentTimeInMilli() {
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
long timeInMilli = date.getTime();
return timeInMilli;
}
/**
* ResultReceiver is used to get values from MyService.class
* It is registered in onResume() &
* unregistered in onPause()
*/
class MyResultReceiver extends ResultReceiver {
public MyResultReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
String strMilliFinished = resultData.getString(MyService.KEY_MSG);
updateUI(Long.parseLong(strMilliFinished));
}
private void updateUI(final long milliFinished) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mCurCounterValue++;
mTvCounter.setText("" + mCurCounterValue);
if(milliFinished == 0) {
//resetting counter values
mShouldSaveValues = false;
mMaxCounterValueInSeconds = MAX_COUNTER;
mCurCounterValue = 0;
SharedPreferences.Editor editor = mSharedPref.edit();
editor.putLong(KEY_SAVED_COUNTER, -1);
editor.putLong(KEY_SAVED_TIME_MILLI, -1);
editor.apply();
}
}
});
}
}
}
Replace your Service code with this:
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.os.ResultReceiver;
import android.util.Log;
public class MyService extends Service {
public static final String KEY_MSG = "msg";
CountDownTimer cdt = null;
private static ResultReceiver mReceiver;
public MyService() {
}
public static void registerReceiver(ResultReceiver receiver) {
mReceiver = receiver;
}
public static void unregisterReceiver() {
mReceiver = null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle bundle = intent.getExtras();
long maxCounterValueInSeconds = bundle.getLong(MainActivity.KEY_COUNTER_SECONDS);
long maxCounter = maxCounterValueInSeconds * 1000;
cdt = new CountDownTimer(maxCounter, 1000) {
public void onTick(long millisUntilFinished) {
sendMessage(1, "" + millisUntilFinished);
}
public void onFinish() {
sendMessage(1, "" + 0);
stopSelf();
}
};
cdt.start();
return START_STICKY;
}
private void sendMessage(int resultCode, String message) {
if (mReceiver != null) {
Bundle bundle = new Bundle();
bundle.putString(KEY_MSG, message);
mReceiver.send(resultCode, bundle);
}
}
#Override
public void onDestroy() {
super.onDestroy();
cdt.cancel();
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
Note: I am using ResultReceiver instead of BroadcastReciver
I have two Activities: MenuScreen and Main. MenuScreen starts Main and finishes himself.
Intent intent = new Intent(this, sp.overview.Main.class);
//All extra intent values
startActivity(intent);
finish();
However when i finish Main and start MenuScreen, it also finishes MenuScreen. Note that the finish is called in the SurfaceView of Main
Intent i = new Intent(context, MenuScreen.class);
((Main)context).finish();
context.startActivity(i);
But I just want to finish Main and go back to MenuScreen. What am I doing wrong?
Manifest:
<application
android:name=".Global"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:largeHeap="true">
<activity
android:name=".MenuScreen"
android:label="#string/app_name"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Main"
android:label="#string/title_activity_menu_screen"
android:screenOrientation="landscape">
</activity>
</application>
MenuScreen:
public class MenuScreen extends Activity {
int subject_value = 0;
boolean training = false;
Global global;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
global = (Global)getApplicationContext();
this.subject_value = global.getSubject();
//Set to full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_menu_screen);
TextView t = (TextView)findViewById(R.id.subject_value);
t.setText(String.valueOf(this.subject_value));
}
#Override
protected void onRestart()
{
super.onRestart();
this.subject_value = global.getSubject();
TextView t = (TextView)findViewById(R.id.subject_value);
t.setText(String.valueOf(this.subject_value));
}
#Override
protected void onStart()
{
super.onStart();
this.subject_value = global.getSubject();
TextView t = (TextView)findViewById(R.id.subject_value);
t.setText(String.valueOf(this.subject_value));
}
#Override
protected void onResume()
{
super.onResume();
this.subject_value = global.getSubject();
TextView t = (TextView)findViewById(R.id.subject_value);
t.setText(String.valueOf(this.subject_value));
}
public void StillOne(View view){
sentExtra(Setting.Layout.Still, Setting.FrameSkip.One);
}
public void sentExtra(Setting.Layout layout, Setting.FrameSkip frameSkip)
{
Intent intent = new Intent(this, sp.overview.Main.class);
intent.putExtra("LAYOUT", layout.getValue());
intent.putExtra("FRAMESKIP", frameSkip.getValue());
intent.putExtra("SUBJECT", this.subject_value);
intent.putExtra("TRAINING", this.training);
finish();
startActivity(intent);
}
public void MotionThree(View view) {
sentExtra(Setting.Layout.Motion, Setting.FrameSkip.Three);
}
public void MotionTwo(View view) {
sentExtra(Setting.Layout.Motion, Setting.FrameSkip.Two);
}
public void MotionOne(View view) {
sentExtra(Setting.Layout.Motion, Setting.FrameSkip.One);
}
public void StillThree(View view) {
sentExtra(Setting.Layout.Still, Setting.FrameSkip.Three);
}
public void StillTwo(View view) {
sentExtra(Setting.Layout.Still, Setting.FrameSkip.Two);
}
public void Plus(View view) {
this.subject_value++;
global.setSubject(this.subject_value);
TextView t = (TextView)findViewById(R.id.subject_value);
t.setText(String.valueOf(this.subject_value));
}
public void Minus(View view) {
this.subject_value--;
global.setSubject(this.subject_value);
TextView t = (TextView)findViewById(R.id.subject_value);
t.setText(String.valueOf(this.subject_value));
}
public void Training(View view) {
this.training = !this.training;
android.widget.Button b = (android.widget.Button)findViewById(R.id.training);
b.setText("Training: " + String.valueOf(this.training));
}
}
Main:
public class Main extends Activity implements SensorEventListener {
private Overview overview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//turn the title off
requestWindowFeature(Window.FEATURE_NO_TITLE);
//set to full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
Intent it = getIntent();
int layout = it.getIntExtra("LAYOUT", 1);
int frameskip = it.getIntExtra("FRAMESKIP", 1);
int subject = it.getIntExtra("SUBJECT", 0);
boolean training = it.getBooleanExtra("TRAINING", false);
Setting s = new Setting(Setting.Layout.getSetting(layout), Setting.FrameSkip.getSetting(frameskip), training);
overview = new Overview(this, s, subject);
setContentView(overview);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return false;
}
#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);
}
#Override
public void onSensorChanged(SensorEvent event) {
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
Overview:
public class Overview extends SurfaceView implements SurfaceHolder.Callback{
private MainLoop loop;
private static Context context;
public int Subject;
public Setting state;
public Overview(Context context, Setting state, int subject) {
super(context);
// Set the context;
this.context = context;
this.state = state;
this.Subject = subject;
//add the callback to the SurfaceHolder to intercept events;
getHolder().addCallback(this);
getHolder().setFormat(PixelFormat.RGBA_8888);
//init the MainLoop
loop = new MainLoop(getHolder(), this, this.state);
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
if(!loop.equals(null))
{
int index = event.getActionIndex();
int id = event.getPointerId(index);
ProgressManager p = loop.progressManager;
PointF pos = null;
switch (event.getActionMasked())
{
case MotionEvent.ACTION_UP:
switch (p.state) {
case Start:
if (!p.loading)
p.state = ProgressManager.Progress.Image;
break;
case Image:
break;
case Pause:
p.state = ProgressManager.Progress.Overview;
break;
case Overview:
pos = new PointF(event.getX(0), event.getY(0));
if(p.trueButton.collide(pos)) {
p.answer = true;
if(p.setting.layout == Setting.Layout.Motion)
p.frameLoader.stop();
p.state = ProgressManager.Progress.Result;
}
if(p.falseButton.collide(pos)) {
p.answer = false;
if(p.setting.layout == Setting.Layout.Motion)
p.frameLoader.stop();
p.state = ProgressManager.Progress.Result;
}
break;
case Result:
if(!p.saving && p.saved) {
Intent i = new Intent(context, MenuScreen.class);
context.startActivity(i);
((Main)context).finish();
}
break;
}
break;
default:break;
}
}
return true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while(retry)
{
try
{
loop.setRunning(false);
loop.join();
retry = false;
// Properly turn of the process (otherwise it creates multiple instances of all objects...)
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
loop.setRunning(true);
loop.start();
}
}
Why are you doing finish MenuScreen? Just start Main activities and do not call finish() in your code. It's will work fine.
But Your code is wrong!
Instead of this code:
Intent i = new Intent(context, MenuScreen.class);
((Main)context).finish();
context.startActivity(i);
Do this:
Intent i = new Intent(context, MenuScreen.class);
context.startActivity(i);
((Main)context).finish();
Hope this help :)
You are finishing your activity and after that u try to open activity(when there is no activity).
replace this lines..
Intent i = new Intent(context, MenuScreen.class);
((Main)context).finish();
context.startActivity(i);
with this..
Intent i = new Intent(context, MenuScreen.class);
context.startActivity(i);
((Main)context).finish();
I'm trying to change my textview, but it doesn't work.
MainActivity:
public void changeTxt(String txt){
TextView t = (TextView) findViewById(R.id.wifiName);
t.setText(txt);
}
BroadcastReceiver:
MainActivity ma;
#Override
public void onReceive(Context context, Intent intent) {
ma= new MainActivity();
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
String txt = acCharge+"";
ma.changeTxt(txt);
}
Call registerBroadCastReciever like this :
//BroadCastReciever variable in base activity or activity
private BroadcastReceiver serviceBroadcastReceiver;
//Register reciever method
void registerBroadcastReceiver(){
if (serviceBroadcastReceiver != null)
{
LocalBroadcastManager.getInstance(this.getActivity()).unregisterReceiver(this.serviceBroadcastReceiver);
LocalBroadcastManager.getInstance(this.getActivity()).registerReceiver(this.serviceBroadcastReceiver, new IntentFilter("...BROADCAST_STR"));
return;
}
this.serviceBroadcastReceiver = new BroadcastReceiver()
{
public void onReceive(Context paramAnonymousContext, Intent paramAnonymousIntent)
{
//Recieve STH and call method like SetText() that initialize your textView text
}
};
LocalBroadcastManager.getInstance(this.getActivity()).registerReceiver(this.serviceBroadcastReceiver, new IntentFilter("...BROADCAST_STR"));
} //Then onResume & onPause methods in activity
#Override
public void onResume() {
super.onResume();
registerBroadcastReceiver();
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(this.serviceBroadcastReceiver);
}
Try this:
MyActivity:
public class MyActivity extends Activity {
private TextView wifi;
private BateryReceiver bateryReceiver;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
wifi = (TextView) findViewById(R.id.wifiName);
wifi.setText("nothing");
bateryReceiver = new BateryReceiver(wifi);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(bateryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(bateryReceiver);
}
}
BateryReceiver: (create new class if you don't have)
public class BateryReceiver extends BroadcastReceiver {
private final TextView textView;
public BateryReceiver(TextView textView)
{
this.textView = textView;
}
#Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean ac = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
boolean usb = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
String plugSource = (ac == true)? "AC" : "USB";
if(isCharging)
textView.setText("charging: " + isCharging + " by " + plugSource);
else
textView.setText("not charging");
}
}
It should be working.