Cannot stop timer in Android? How to solve it? - android

I am writing a class to control start and stop timer in Android. The controller is an Activity that will send start or stop value. In the TimerControl class, I write two functions that use to start and stop the timer. I can start the timer, but I cannot stop it. How can I solve it? This is my code
//In Controller class
//===========Start========
Intent smsTimer = new Intent(getApplicationContext(), TimmerControl.class);
smsTimer.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
smsTimer.putExtra("input_timer", "start");
getApplicationContext().startActivity(smsTimer);
//===========Stop========
Intent smsTimer = new Intent(getApplicationContext(), TimmerControl.class);
smsTimer.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
smsTimer.putExtra("input_timer", "stop");
getApplicationContext().startActivity(smsTimer);
This is my code of TimerControl
public class TimmerControl extends Activity {
private CountDownTimer timer_SMS;
private String TAG="TimmerControl";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent != null &&intent.getExtras() != null) {
Bundle bundle = intent.getExtras();
if (!bundle.getString("input_timer").equals(null)) {
String input_timer = bundle.getString("input_timer");
if(input_timer.equals("start")) {// start
startSMSTimer();
}
else if(input_timer.equals("stop")) {// stop
stopSMSTimer();
}
else{}
}
}
finish();
}
public void startSMSTimer(){
if (timer_SMS != null) {
timer_SMS.cancel();
timer_SMS = null;
}
timer_SMS = new CountDownTimer(100000, 20000) {
#Override
public void onTick(long millisUntilFinished) {
long timOver = 100000 - millisUntilFinished;
Log.d(TAG, String.valueOf(timOver));
}
#Override
public void onFinish() { }
};
timer_SMS.start();
}
public void stopSMSTimer(){
if (timer_SMS != null) {
timer_SMS.cancel();
timer_SMS = null;
}
}
}

You need to send "stop" while sending intent for stop as follows :
//In Controller class
//===========Start========
Intent smsTimer = new Intent(getApplicationContext(), TimmerControl.class);
smsTimer.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
smsTimer.putExtra("input_timer", "start"); // start
getApplicationContext().startActivity(smsTimer);
//===========Stop========
Intent smsTimer = new Intent(getApplicationContext(), TimmerControl.class);
smsTimer.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
smsTimer.putExtra("input_timer", "stop"); // stop
getApplicationContext().startActivity(smsTimer);

public class TimmerControl extends Service {
CountDownTimer timer_SMS;
private BroadcastReceiver mReceiver;
#Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("start");
intentFilter.addAction("stop");
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//extract our message from intent
if (intent.getAction().equals("start")) {
startSMSTimer();
}
if (intent.getAction().equals("stop")) {
stopSMSTimer();
}
}
};
this.registerReceiver(mReceiver, intentFilter);
}
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(this.mReceiver);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void startSMSTimer() {
if (timer_SMS != null) {
timer_SMS.cancel();
timer_SMS = null;
}
timer_SMS = new CountDownTimer(100000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
long timOver = 100000 - millisUntilFinished;
Log.e("Time: ", ""+timOver);
}
#Override
public void onFinish() {
Log.e("finished: ","");
}
};
timer_SMS.start();
}
public void stopSMSTimer() {
if (timer_SMS != null) {
timer_SMS.cancel();
timer_SMS = null;
Log.e("Stop: ","");
}
stopSelf();
}
}
SMSControllerActivity.java
public class SMSControllerActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_smscontroller);
findViewById(R.id.btn_start).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!isServiceRunning(TimmerControl.class))
startService(new Intent(SMSControllerActivity.this, TimmerControl.class));
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
sendBroadcast(new Intent("start"));
}
}, 500);
}
});
findViewById(R.id.btn_stop).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendBroadcast(new Intent("stop"));
}
});
;
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
activity_smscontroller.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/btn_start"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Start" />
<Button
android:id="#+id/btn_stop"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Stop" />
</LinearLayout>

Related

MediaBrowserServiceCompat stopped playing music when app goes background

Mediabrowsercompat not playing the music when app goes background. If I don't disconnect the mediabrowsercompat instance in activity onStop method then it is working. But that is not the solution as according to documentation we have to disconnect the service once app goes background.
This is my mediabroweserservicecomat class (I am using Exoplayer to play music):
private static final String PLAYBACK_CHANNEL_ID = "100";
private static final int PLAYBACK_NOTIFICATION_ID =101 ;
private MediaSessionCompat mediaSessionCompat;
private PlaybackStateCompat.Builder stateBuilder;
private SimpleExoPlayer exoPlayer;
private Uri oldUri;
private AudioAttributes audioAttributes;
private PlayerNotificationManager playerNotificationManager;
#Override
public void onCreate() {
super.onCreate();
Log.i("Test","Hi");
initPlayer();
initAttributes();
ComponentName mediaButtonReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class);
mediaSessionCompat = new MediaSessionCompat(getApplicationContext(), "Tag", mediaButtonReceiver, null);
mediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS|
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
stateBuilder = new PlaybackStateCompat.Builder();
stateBuilder.setActions(PlaybackStateCompat.ACTION_PLAY|PlaybackStateCompat.ACTION_PLAY_PAUSE);
mediaSessionCompat.setPlaybackState(stateBuilder.build());
mediaSessionCompat.setCallback(mediaSessionCompatCallback);
setSessionToken(mediaSessionCompat.getSessionToken());
mediaSessionCompat.setActive(true);
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setClass(this, MediaButtonReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0);
mediaSessionCompat.setMediaButtonReceiver(pendingIntent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MediaButtonReceiver.handleIntent(mediaSessionCompat,intent);
return super.onStartCommand(intent, flags, startId);
}
private MediaSessionCompat.Callback mediaSessionCompatCallback = new MediaSessionCompat.Callback() {
#Override
public void onPlayFromUri(Uri uri, Bundle extras) {
super.onPlayFromUri(uri, extras);
if (uri!=null){
MediaItem mediaSource = MediaItem.fromUri(uri);
if (uri!=oldUri){
play(mediaSource);
onPlay();
}else {
oldUri = uri;
}
}
}
#Override
public void onPlay() {
super.onPlay();
Log.i("onPlay","onPlay");
//startService(new Intent(MusicService.this,MusicForegroundService.class));
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(MusicService.this,
PLAYBACK_CHANNEL_ID, R.string.channel_name, PLAYBACK_NOTIFICATION_ID,
new PlayerNotificationManager.MediaDescriptionAdapter() {
#Override
public CharSequence getCurrentContentTitle(Player player) {
return "title";
}
#Nullable
#Override
public PendingIntent createCurrentContentIntent(Player player) {
Intent intent = new Intent(getBaseContext(), PlayerFullViewActivity.class);
return PendingIntent.getActivity(getBaseContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
#Nullable
#Override
public CharSequence getCurrentContentText(Player player) {
return "content";
}
#Nullable
#Override
public Bitmap getCurrentLargeIcon(Player player, PlayerNotificationManager.BitmapCallback callback) {
return null;
}
},
new PlayerNotificationManager.NotificationListener() {
#Override
public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
startForeground(notificationId,notification);
}
#Override
public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
stopSelf();
}
});
playerNotificationManager.setPlayer(exoPlayer);
}
#Override
public void onPause() {
super.onPause();
pause();
}
#Override
public void onStop() {
playerNotificationManager.setPlayer(null);
super.onStop();
stop();
}
};
#Override
public void onDestroy() {
super.onDestroy();
stop();
}
private void stop() {
exoPlayer.setPlayWhenReady(false);
exoPlayer.release();
exoPlayer =null;
updatePlayBackState(PlaybackStateCompat.STATE_NONE);
mediaSessionCompat.setActive(false);
mediaSessionCompat.release();
}
#SuppressLint("WrongConstant")
private void pause() {
if (exoPlayer!=null){
exoPlayer.setPlayWhenReady(false);
if (exoPlayer.getPlaybackState()==PlaybackStateCompat.STATE_PLAYING){
updatePlayBackState(PlaybackStateCompat.STATE_PAUSED);
}
}
}
private void play(MediaItem mediaSource){
if (exoPlayer==null) {
initPlayer();
}
if (audioAttributes==null) {
initAttributes();
}
exoPlayer.setAudioAttributes(audioAttributes,true);
exoPlayer.setMediaItem(mediaSource);
exoPlayer.prepare();
play();
}
private void initAttributes() {
audioAttributes = new AudioAttributes.Builder().setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MUSIC)
.build();
}
private void initPlayer() {
exoPlayer = new SimpleExoPlayer.Builder(this, new DefaultRenderersFactory(getBaseContext()),
new DefaultExtractorsFactory()).build();
}
private void play() {
exoPlayer.setPlayWhenReady(true);
updatePlayBackState(PlaybackStateCompat.STATE_PLAYING);
mediaSessionCompat.setActive(true);
}
private void updatePlayBackState(int statePlaying) {
mediaSessionCompat.setPlaybackState(new PlaybackStateCompat.Builder().
setState(statePlaying,0L,0).build());
}
#Nullable
#Override
public BrowserRoot onGetRoot(#NonNull String clientPackageName, int clientUid, #Nullable Bundle rootHints) {
return new BrowserRoot("",null);
}
#Override
public void onLoadChildren(#NonNull String parentId, #NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
result.sendResult(null);
}
This is my activity class:
ActivityPlayerFullViewBinding activityPlayerFullViewBinding;
private MediaBrowserCompat mediaBrowserCompat;
private MediaBrowserCompat.ConnectionCallback connectionCallback = new MediaBrowserCompat.ConnectionCallback(){
#Override
public void onConnected() {
super.onConnected();
MediaSessionCompat.Token sessionToken = mediaBrowserCompat.getSessionToken();
if (sessionToken!=null){
try {
MediaControllerCompat mediaControllerCompat = new
MediaControllerCompat(PlayerFullViewActivity.this, sessionToken);
MediaControllerCompat.setMediaController(PlayerFullViewActivity.this,mediaControllerCompat);
playPauseBuild();
Log.d("onConnected","ConnectionSuccess");
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
#Override
public void onConnectionFailed() {
super.onConnectionFailed();
Log.d("onConnectionFaild","ConnectionFailed");
}
};
MediaControllerCompat.Callback controllerCallback =
new MediaControllerCompat.Callback() {
#Override
public void onMetadataChanged(MediaMetadataCompat metadata) {}
#Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityPlayerFullViewBinding = DataBindingUtil.setContentView(this,R.layout.activity_player_full_view);
ComponentName componentName = new ComponentName(this,MusicService.class);
mediaBrowserCompat = new MediaBrowserCompat(this,componentName,connectionCallback,null);
}
private void playPauseBuild() {
MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(PlayerFullViewActivity.this);
activityPlayerFullViewBinding.playPauseBtn
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int state = mediaController.getPlaybackState().getState();
if (state== PlaybackStateCompat.STATE_PAUSED||state==PlaybackStateCompat.STATE_STOPPED||
state==PlaybackStateCompat.STATE_NONE){
mediaController.getTransportControls().playFromUri(
Uri.parse("https://www.mboxdrive.com/Eminem-Sing-For-The-Moment9jamo.com_.mp3"),null);
activityPlayerFullViewBinding.playPauseBtn.setText("Pause");
}else if (state == PlaybackStateCompat.STATE_PLAYING ||
state == PlaybackStateCompat.STATE_BUFFERING ||
state == PlaybackStateCompat.STATE_CONNECTING){
mediaController.getTransportControls().pause();
activityPlayerFullViewBinding.playPauseBtn.setText("Play");
}
}
});
mediaController.registerCallback(controllerCallback);
}
#Override
protected void onStart() {
super.onStart();
mediaBrowserCompat.connect();
}
#Override
public void onResume() {
super.onResume();
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
#Override
protected void onStop() {
super.onStop();
Log.i("onStop","onStop");
MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(this);
if (mediaController != null) {
mediaController.unregisterCallback(controllerCallback);
}
mediaBrowserCompat.disconnect();
}
After wasting 2 sleepless nights. I found a workaround. I don't know whether it's a correct way to handle this. But if you have ever faced this problem. You can try it:
#Override
protected void onStart() {
super.onStart();
if (!mediaBrowserCompat.isConnected())
mediaBrowserCompat.connect();
}
#Override
protected void onStop() {
super.onStop();
Log.i("onStop","onStop");
MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(this);
if (mediaController != null) {
mediaController.unregisterCallback(controllerCallback);
}
// mediaBrowserCompat.disconnect();
}
#Override
protected void onDestroy() {
super.onDestroy();
mediaBrowserCompat.disconnect();
}

Trouble running background service Android

I have some simple code intended to start a background service that updates a static integer from my MainActivity every second. I also have a button that when clicked, updates a TextView with the value of that static integer. However, every time I start the service, it only increments the value once and stops, instead of continuously incrementing it until I press stop service.
This is my code:
public class MainActivity extends AppCompatActivity {
public static int count;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
count = 0;
}
public void pressButton(View view) {
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText("" + count);
}
public void startService(View view) {
startService(new Intent(getBaseContext(), MyService.class));
}
public void stopService(View view) {
stopService(new Intent(getBaseContext(), MyService.class));
}
}
And my service:
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
MainActivity.count++;
}
}, 1000);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
I can't figure out what seems to be the problem.
public class DownloadService extends IntentService {
String pdfName = "";
public DownloadService() {
super("DownloadService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
showNotificationProgress();
if (intent != null) {
pdfName = intent.getStringExtra("pdfName");
}
downloadPDF ( ) // Implement this method
}
public void writeBytesToFile(boolean status, String encodedString) {
if (status && !TextUtils.isEmpty(encodedString)) {
byte[] decodedArry = decodeBase64String(encodedString);
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + pdfName;
File fileOut = new File(path);
// if file doesnt exists, then create it
if (!fileOut.exists()) {
try {
//noinspection ResultOfMethodCallIgnored
fileOut.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try (FileOutputStream fileOuputStream = new FileOutputStream(fileOut)) {
fileOuputStream.write(decodedArry);
completed = true;
} catch (IOException e) {
completed = false;
e.printStackTrace();
} finally {
if (completed) {
//do something
}
}
} else {
hideNotificationProgress();
}
}
private static byte[] decodeBase64String(String encodedString) {
return Base64.decode(encodedString, Base64.DEFAULT);
}
public static void hideNotificationProgress() {
mNotifyManager.cancel(1);
}
private void showNotificationProgress() {
final int id = 1;
mNotifyManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("PDF Download")
.setContentText("Download in progress")
.setSmallIcon(android.R.drawable.stat_sys_download);
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
#Override
public void run() {
// Do the "lengthy" operation 20 times
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(0, 0, true);
// Issues the notification
mNotifyManager.notify(id, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
}
}
Why don't you try Intent Service like this.
And start this service as below
Intent intent = new Intent(AActivity, DownloadService.class);
intent.putExtra("pdfName", pdfName);
holdingActivity.startService(intent);
This code shows how to update the UI in an Android Activity from a background Service.
BroadcastTest.java
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.widget.TextView;
public class BroadcastTest extends Activity {
private static final String TAG = "BroadcastTest";
private Intent intent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
intent = new Intent(this, BroadcastService.class);
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
#Override
public void onResume() {
super.onResume();
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(BroadcastService.BROADCAST_ACTION));
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
stopService(intent);
}
private void updateUI(Intent intent) {
String counter = intent.getStringExtra("counter");
String time = intent.getStringExtra("time");
Log.d(TAG, counter);
Log.d(TAG, time);
TextView txtDateTime = (TextView) findViewById(R.id.txtDateTime);
TextView txtCounter = (TextView) findViewById(R.id.txtCounter);
txtDateTime.setText(time);
txtCounter.setText(counter);
}
}
BroadcastService.java
import java.util.Date;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class BroadcastService extends Service {
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "com.websmithing.broadcasttest.displayevent";
private final Handler handler = new Handler();
Intent intent;
int counter = 0;
#Override
public void onCreate() {
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo();
handler.postDelayed(this, 10000); // 10 seconds
}
};
private void DisplayLoggingInfo() {
Log.d(TAG, "entered DisplayLoggingInfo");
intent.putExtra("time", new Date().toLocaleString());
intent.putExtra("counter", String.valueOf(++counter));
sendBroadcast(intent);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
handler.removeCallbacks(sendUpdatesToUI);
super.onDestroy();
}
}
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TableLayout android:id="#+id/tableGPS"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="7px"
android:stretchColumns="1">
<TableRow
android:layout_margin="1dip">
<TextView android:layout_gravity="right"
android:text="Time:"
android:layout_marginRight="7px"
android:layout_width="60px" />
<TextView android:id="#+id/txtDateTime"
android:gravity="left"
android:layout_span="2" />
</TableRow>
<TableRow
android:layout_margin="1px">
<TextView android:layout_gravity="right"
android:text="Counter:"
android:layout_marginRight="7px"
android:layout_width="60px" />
<TextView android:id="#+id/txtCounter"
android:gravity="left" />
</TableRow>
</TableLayout>
</LinearLayout>
Post delay only runs one time. You need to schedule a reoccurring task or just create a Runnable that will recall the task over and over.
final Handler mHandler = new Handler();
Runnable runner = new Runnable() {
#Override
public void run() {
MainActivity.count++;
mHandler.postDelayed(runner, 1000);
}
}
mHandler.postDelayed(runner, 1000);

sinch conference call hung up right after it starts

I managed to start a conference call cut it closes right after I start it with HUNG_UP cause and I got this in my log:
11-03 17:28:08.940: E/sinch-android-rtc(19101): peermediaconnection: virtual void rebrtc::SetSDPObserver::OnFailure(const string&)Failed to set remote answer sdp: Offer and answer descriptions m-lines are not matching. Rejecting answer.
11-03 17:28:08.940: E/sinch-android-rtc(19101): mxp: Failed to set remote answer sdp: Offer and answer descriptions m-lines are not matching. Rejecting answer.
can anybody help me solve this please?
Edit:
my scenario is when a user clicks the call button I ask him if he wants to start a new call or join an already created one.
I managed to make my code from this question (Sinch conference call error) work as my GroupService class had some bugs.
I start my call like this:
Intent intent1 = new Intent(CreateGroupCallActivity.this,SinchClientService.class);
intent1.setAction(SinchClientService.ACTION_GROUP_CALL);
String id = String.valueOf(uid) + "-" + call_id.getText().toString();
intent1.putExtra(SinchClientService.INTENT_EXTRA_ID,id);
startService(intent1);
and in my SinchClientService:
if(intent.getAction().equals(ACTION_GROUP_CALL))
{
String id = intent.getStringExtra(INTENT_EXTRA_ID);
if(id != null)
groupCall(id);
}
public void groupCall(String id) {
if (mCallClient != null) {
Call call = mCallClient.callConference(id);
CurrentCall.currentCall = call;
Log.d("call", "entered");
Intent intent = new Intent(this, GroupCallService.class);
startService(intent);
}
}
nd here is my GroupCallService
public class GroupCallScreenActivity extends AppCompatActivity implements ServiceConnection {
private SinchClientService.MessageServiceInterface mMessageService;
private GroupCallService.GroupCallServiceInterface mCallService;
private UpdateReceiver mUpdateReceiver;
private ImageButton mEndCallButton;
private TextView mCallDuration;
private TextView mCallState;
private TextView mCallerName;
//private TextView locationview;
private ImageView user_pic;
private long mCallStart;
private Timer mTimer;
private UpdateCallDurationTask mDurationTask;
ImageButton chat;
ImageButton speaker;
ImageButton mic;
boolean speaker_on = false;
boolean mic_on = true;
PowerManager mPowerManager;
WakeLock mProximityWakeLock;
final static int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
com.galsa.example.main.ImageLoader mImageLoader;
/*String location;
String longitude;
String latitude;*/
private class UpdateCallDurationTask extends TimerTask {
#Override
public void run() {
GroupCallScreenActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
updateCallDuration();
}
});
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
setContentView(R.layout.callscreen);
doBind();
mCallDuration = (TextView) findViewById(R.id.callDuration);
mCallerName = (TextView) findViewById(R.id.remoteUser);
mCallState = (TextView) findViewById(R.id.callState);
//locationview = (TextView) findViewById(R.id.location);
mEndCallButton = (ImageButton) findViewById(R.id.hangupButton);
chat = (ImageButton) findViewById(R.id.chat);
chat.setVisibility(View.GONE);
speaker = (ImageButton) findViewById(R.id.speaker);
mic = (ImageButton) findViewById(R.id.mic);
user_pic = (ImageView) findViewById(R.id.user_pic);
/*location = getIntent().getStringExtra("location");
longitude = getIntent().getStringExtra("longitde");
latitude = getIntent().getStringExtra("latitude");
locationview.setText(location);*/
mImageLoader = new com.galsa.example.main.ImageLoader(GroupCallScreenActivity.this, R.dimen.caller_image_height);
//mCallerName.setText(mCall.getRemoteUserId());
mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mProximityWakeLock = mPowerManager.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, Utils.TAG);
/*chat.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(GroupCallScreenActivity.this, MessagingActivity.class);
intent.putExtra(SinchClientService.INTENT_EXTRA_ID, mCallService.getCallerId());
intent.putExtra(SinchClientService.INTENT_EXTRA_NAME, mCallService.getCallerName());
startActivity(intent);
}
});*/
speaker.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(speaker_on)
{
mMessageService.speakerOn(speaker_on);
speaker_on = false;
speaker.setImageResource(R.drawable.speaker_off);
}
else
{
mMessageService.speakerOn(speaker_on);
speaker_on = true;
speaker.setImageResource(R.drawable.speaker_on);
}
}
});
mic.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(mic_on)
{
mMessageService.micOn(mic_on);
mic_on = false;
mic.setImageResource(R.drawable.mic_off);
}
else
{
mMessageService.micOn(mic_on);
mic_on = true;
mic.setImageResource(R.drawable.mic_on);
}
}
});
mEndCallButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mCallService.endCall();
}
});
mCallStart = System.currentTimeMillis();
}
private void doBind() {
Intent intent = new Intent(this, SinchClientService.class);
bindService(intent, this, BIND_AUTO_CREATE);
intent = new Intent(this, GroupCallService.class);
bindService(intent, this, BIND_AUTO_CREATE);
}
private void doUnbind() {
unbindService(this);
}
#Override
protected void onStart() {
super.onStart();
mUpdateReceiver = new UpdateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(GroupCallService.ACTION_FINISH_CALL_ACTIVITY);
filter.addAction(GroupCallService.ACTION_CHANGE_AUDIO_STREAM);
filter.addAction(GroupCallService.ACTION_UPDATE_CALL_STATE);
LocalBroadcastManager.getInstance(this).registerReceiver(mUpdateReceiver, filter);
}
#Override
public void onResume() {
super.onResume();
if(mProximityWakeLock != null && !mProximityWakeLock.isHeld()){
mProximityWakeLock.acquire();
}
mTimer = new Timer();
mDurationTask = new UpdateCallDurationTask();
mTimer.schedule(mDurationTask, 0, 500);
}
#Override
public void onPause() {
super.onPause();
if(isFinishing() && mProximityWakeLock != null && mProximityWakeLock.isHeld()){
mProximityWakeLock.release();
}
mDurationTask.cancel();
}
#Override
protected void onStop() {
super.onStop();
if(isFinishing() && mProximityWakeLock != null && mProximityWakeLock.isHeld()){
mProximityWakeLock.release();
}
if(mUpdateReceiver != null)
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mUpdateReceiver);
mUpdateReceiver = null;
}
}
#Override
public void onBackPressed() {
// User should exit activity by ending call, not by going back.
}
private void updateCallDuration() {
mCallDuration.setText(Utils.formatTimespan(System.currentTimeMillis() - mCallStart));
}
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
if(iBinder instanceof GroupCallService.GroupCallServiceInterface)
{
mCallService = (GroupCallService.GroupCallServiceInterface) iBinder;
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
ActionBar actionBar = getSupportActionBar();
if(mCallService.getCallerName() != null)
actionBar.setTitle(mCallService.getCallerName());
else
actionBar.setTitle("Group call");
actionBar.setIcon(R.drawable.callscreen);
if(mCallService.getCallerName() != null)
mCallerName.setText(mCallService.getCallerName());
else
mCallerName.setText("Group call");
mCallState.setText(mCallService.getCallState());
String pic = ChatDatabaseHandler.getInstance(this).getFriendpic(mCallService.getCallerId());
mImageLoader.displayImage(UserFunctions.hostImageDownloadURL + pic, user_pic);
}
else
mMessageService = (SinchClientService.MessageServiceInterface) iBinder;
mMessageService.enableMic();
mMessageService.disableSpeaker();
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mMessageService = null;
mCallService = null;
}
#Override
public void onDestroy() {
if(mUpdateReceiver != null)
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mUpdateReceiver);
mUpdateReceiver = null;
}
doUnbind();
super.onDestroy();
}
private class UpdateReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if(GroupCallService.ACTION_FINISH_CALL_ACTIVITY.equals(intent.getAction()))
{
finish();
}
else if(GroupCallService.ACTION_CHANGE_AUDIO_STREAM.equals(intent.getAction()))
{
setVolumeControlStream(intent.getIntExtra("STREAM_TYPE", AudioManager.USE_DEFAULT_STREAM_TYPE));
}
else if(GroupCallService.ACTION_UPDATE_CALL_STATE.equals(intent.getAction()))
{
mCallState.setText(intent.getStringExtra("STATE"));
}
}
}
}
I start the call with the same way whether the user will start a new call or join a created one.

Timer on onDraw

start button -> game.class -> gameview.class then loop again on game.class when player finish the 1st level it will call gameview.class to generate again the 2nd level. My problem is that my timer will also regenerate and restarts when going on the 2nd level. How can I make my timer pause and resume in this kind of flow of game?
on my Game.Class:
public void onCreate(Bundle savedInstanceState) {
timeCounter = new TimeCounter();
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
this.maze = (Maze) getLastNonConfigurationInstance();
if (this.maze == null) {
this.maze = (Maze) extras.get("maze");
}
gview = new GameView(this);
gview.setTimeCounter(timeCounter);
gview.setMaze(this.maze);
setContentView(gview);
and on my GameView.Class:
protected void onDraw(Canvas canvas) {
if (startTimer) {
timeCounter.start();
invalidate();
int secondss = timeCounter.getTimeSeconds();
String text = String.format("%02d:%02d", secondss / 60,
secondss % 60);
timer.getTextBounds(text, 0, text.length(), textBounds);
canvas.drawText(text, (this.getWidth() - textBounds.right) - 5,
(this.getHeight() - textBounds.bottom) - 5, timer);
}
and when the 1st level finish it will call this method:
void shownextmaze() {
Random rand = new Random();
Intent game = new Intent(context, Game.class);
nextmaze = rand.nextInt(6) + 1;
Maze maze = MazeCreator.getMaze(nextmaze);
game.putExtra("maze", maze);
context.startActivity(game);
timeCounter.resume();
}
How can I make my timer run until the 4 levels are cleared?
It is logical that onDraw will be called and timer will be start again. You should start your timer in a service and run it in background thread. Each time you want to access it value you can bind to service.
Check this guideline.
In this code each time you open the app you will see updated value:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(MainActivity.this, MyService.class));
doBindService();
((Button) findViewById(R.id.button1))
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mBoundService != null) {
((TextView) findViewById(R.id.textView1))
.setText(mBoundService.getValue() + "");
}
}
});
((Button) findViewById(R.id.button2))
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mBoundService = null;
stopService(new Intent(MainActivity.this,
MyService.class));
doUnbindService();
}
});
}
private MyService mBoundService;
private boolean mIsBound;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mBoundService = ((MyService.LocalBinder) service).getService();
((TextView) findViewById(R.id.textView1)).setText(mBoundService
.getValue() + "");
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
}
};
void doBindService() {
bindService(new Intent(MainActivity.this, MyService.class),
mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
}
And a service:
public class MyService extends Service {
private final IBinder mBinder = new LocalBinder();
// private TimeCounter timeCounter;
int x = 0;
public class LocalBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
#Override
public void onCreate() {
new Thread(new Runnable() {
public void run() {
while (true) {
x++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public int getValue() {
return x;
}
}
Maybe you need activity_main.xml:
<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"
tools:context="${relativePackage}.${activityClass}" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/textView1"
android:text="Show Updated value" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/button1"
android:layout_marginTop="28dp"
android:text="Stop Service" />
</RelativeLayout>

android - how can I stop the thread inside the service?

I have a checked button in my MainActivity. If that button is checked it should start the service but if a user unchecked the button I want to stop the service.
So in uncheck condition I have written this stopService(intentname); but the problem is the service is not stopping. Here is my code snippet:
Service Class
public class SimpleService extends Service
{
String selectedAudioPath = "";
private MyThread myythread;
public Intent intent;
public boolean isRunning = false;
long interval=30000;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
myythread = new MyThread(interval);
}
#Override
public synchronized void onDestroy()
{
super.onDestroy();
if(!isRunning)
{
myythread.interrupt();
myythread.stop();
isRunning = false;
}
}
#Override
public synchronized void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
if(!isRunning)
{
//this.intent = intent;
//System.out.println("the intent is" + intent);
myythread.start();
isRunning = true;
}
}
class MyThread extends Thread
{
long interval;
public MyThread(long interval)
{
this.interval=interval;
}
#Override
public void run()
{
while(isRunning)
{
System.out.println("Service running");
try
{
String myString = intent.getStringExtra("name");
if(myString == null)
Log.d("Service","null");
else
{
Log.d("Service","not null");
if(myString.equalsIgnoreCase("image"))
{
uploadImages();
Thread.sleep(interval);
}
else if(myString.equalsIgnoreCase("audio"))
{
uploadAudio();
Thread.sleep(interval);
}
}
}
catch (InterruptedException e)
{
isRunning = false;
e.printStackTrace();
}
}
}
You can't stop a thread that has a running unstoppable loop like this
while(true)
{
}
To stop that thread, declare a boolean variable and use it in while-loop condition.
public class MyService extends Service {
...
private Thread mythread;
private boolean running;
#Override
public void onDestroy()
{
running = false;
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
running = true;
mythread = new Thread() {
#Override
public void run() {
while(running) {
MY CODE TO RUN;
}
}
};
};
mythread.start();
}
Source: Stopping a thread inside a service
Don't use Threads. Use AsyncTask instead.
public class MyService extends Service {
private AsyncTask<Void,Void,Void> myTask;
#Override
public void onDestroy(){
super.onDestroy();
myTask.cancel(true);
}
#Override
public void onStart(Intent intent, int startid) {
myTask = new AsyncTask<Void,Void,Void>(){
#Override
public void doInBackground(Void aVoid[]){
doYourWorkHere();
}
}
myTask.execute();
}
}

Categories

Resources