Problem with startService. How to fix it? - java

I have a start activity which is using services to play a background sound and after 5 seconds another activity is loaded.
The problem is in the second activity the sound doesn't load or service doesn't work... i'm not sure what is happening.
Sound works in the first activity when the app start.
here is the first activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//remove window title and make it fullscreen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//bind activity
setContentView(R.layout.start_activity);
ButterKnife.bind(this);
Intent intent = new Intent(StartActivity.this, SoundService.class);
intent.putExtra("filename", "audiostart");
//start service and start music
startService(intent);
int TIME_OUT = 5000;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(StartActivity.this, AvatarsActivity.class);
startActivity(i);
finish();
}
}, TIME_OUT);
Log.d(TAG, "APP Started!");
}
#Override
protected void onDestroy() {
//stop service and stop music
stopService(new Intent(StartActivity.this, SoundService.class));
super.onDestroy();
}
and the second activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.avatars_activity);
ButterKnife.bind(this);
Intent intent = new Intent(AvatarsActivity.this, SoundService.class);
intent.putExtra("filename", "audioavatars");
//start service and start music
startService(intent);
}
#Override
protected void onDestroy() {
//stop service and stop music
stopService(new Intent(AvatarsActivity.this, SoundService.class));
super.onDestroy();
}
here is the service:
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
player = MediaPlayer.create(this, R.raw.audio);
player.setLooping(false);
}
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null){
String mFilename = intent.getStringExtra("filename");
Toast toast = Toast.makeText(getApplicationContext(), "Filename: " + mFilename, Toast.LENGTH_SHORT);
toast.show();
}
player.start();
return Service.START_NOT_STICKY;
}
public void onDestroy() {
player.stop();
player.release();
stopSelf();
super.onDestroy();
}
I want a background sound when the second activity loads after 5 seconds passed in first activity.
And a second problem is that i want to pass a variable in onCreate method in service with what sound to play depending on the activity. (This task i think i can do it but doesn't hurt to ask opinions how to do it)

Your code seems fine. But have you registered your service in your manifest file? Please check your manifest. Your service is not registered can be possible cause.

You are starting second activity after 5sec delay and immediately, after you queue start intent, you call finish() on first activity which will trigger onDestroy callback of the same activity. In onDestroy() of that 1st activity you implemented stop service, which causes service to stop.
Remove that implementation of onDestroy() in both activities and provide to user a way to stop service explicitly (clicking on a button or whatever) instead of doing it in a activity lifecycle callback.

Related

Can't cancel a notification after updating it

I'm developing a countdown app, and currently trying to show a notification when you exit the app while the countdown is running. Correspondingly, I want the notification to disappear when the user returns to the app.
So far I've managed to make it work for a simple notification with static text, do the following: in MainActivity.java, in onStop(), I create an intent and initiate the service with startService(intent). Symmetrically, in onStart() I run stopService(intent) so that when you return to the app the service gets canceled. This works like a charm, the notification appears and disappears when it must.
The next step has been trying to make the notification show a text that varies (it will say "X minutes remaining"). According to the info out there, to update an existing notification you have to create a new one, give it the same ID as the existing one, and call .notify of a NotificationManager. When I do this the notification indeed gets updated correctly (the text changes as expected), BUT: now, returning to the main activity does not cancel the notification. The icon stays up there and doesn't get interrupted.
I've been trying to solve this for hours and hours. I've also tried hacks like sending signals via shared preferences to tell the service to stop, but for some reason, it seems to completely ignore the command stopself() too.
Does anybody have a suggestion of what could be the cause? Any help would be greatly appreciated. Here is the relevant code:
MainActivity.java:
#Override
protected void onStart() {
super.onStart();
Intent serviceIntent = new Intent(getBaseContext(), CounterService.class);
stopService(serviceIntent);
}
protected void onStop() {
super.onStop();
Intent serviceIntent = new Intent(getBaseContext(), CounterService.class);
startService(serviceIntent);
}
CounterService.java:
public class CounterService extends Service {
Notification notification;
NotificationManager notificator;
Intent intentNoti;
CountDownTimer counter;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intentNoti = new Intent(this, MainActivity.class);
final PendingIntent pending = PendingIntent.getActivity(this, 0, intentNoti, 0);
final Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.common_full_open_on_phone);
//Countdown
counter = new CountDownTimer (30000, 1000) {
public void onTick(long millisUntilFinished) {
String time = String.valueOf(System.currentTimeMillis());
notification = new Notification.Builder(CounterService.this)
.setContentTitle("Name")
.setContentText(time)
.setSmallIcon(R.drawable.icon_start)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pending)
.setOngoing(true).build();
notificator = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificator.notify(1001, notification);
}
public void onFinish() {
}
}.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
counter.cancel();
}
}
First create a Timer like this
private Timer timer;
private TimerTask timerTask;
public void startTimer() {
timer = new Timer();
timerTask = new TimerTask() {
public void run() {
// Add your code
}
};
timer.schedule(timerTask, 1000, 1000); //
}
Also you need to stop your timer.
So
public void stoptimertask() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
Call StartTimer and StopTimer in OnStartCommand() and onDestroy() respectively. Add these lines in onDestroy()
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, Restarter.class);
this.sendBroadcast(broadcastIntent);
it can be handled in multiple ways, you have not stopped your timer
Note:- posting code in Kotlin
1)
override fun onDestroy() {
counter.cancel()
}
in your activity
override fun onResume() {
super.onResume()
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancelAll()
}

How to start a video (Inside an activity) when a call is answered and stop the activity when the call is ended?

My code is working perfectly, i used a Brodcast Receiver.
In my application when the user click a button, a phone call is started, and the second activity (outcall.java) popup the screen, in the outcall Activity i have a VideoView, what I want to do is that the Video starts when the call is answered, and the activity is killed when the call is ended.
I have another problem with my code, i want the second activity to launch only when I use the button inside the application, because now it launches always even if i call a friend.
help will be appreciated
Here is my MainActivity
public class MainActivity extends AppCompatActivity {
Button play;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(broadcastReceiver, new IntentFilter(""));
play = (Button)findViewById(R.id.button2);
final MediaPlayer mP=MediaPlayer.create(MainActivity.this,R.raw.reco);
play.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
if (mP.isPlaying()){
mP.pause();
play.setBackgroundResource(R.drawable.play);
}else {
mP.start();
play.setBackgroundResource(R.drawable.pause);
}
}
});
ActivityCompat.requestPermissions(this, new String[]{CALL_PHONE}, PackageManager.PERMISSION_GRANTED);
}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
OpenCallOut();
}
};
public void OpenCallOut(){
Intent intent = new Intent(this, Outcall.class);
startActivity(intent);
}
public void CallButton(View view) {
if (checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
return;
}
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "123456"));
startActivity(intent);
}
#Override
public void onDestroy() {
finish();
System.exit(0);
}
}
Here is my Broadcast, i found this in codetoart but don't know how to use it
public class Broadcast extends BroadcastReceiver {
private static final String TAG = "PhoneStateBroadcastReceiver";
Context mContext;
String incoming_nr;
private int prev_state;
#Override
public void onReceive(Context context, Intent intent) {
context.sendBroadcast(new Intent(""));
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Bundle bundle = intent.getExtras();
String phoneNr= bundle.getString("incoming_number");
Log.v(TAG, "phoneNr: "+phoneNr);
mContext=context;
}
public class CustomPhoneStateListener extends PhoneStateListener {
private static final String TAG = "CustomPhoneStateListener";
#Override
public void onCallStateChanged(int state, String incomingNumber){
if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "CALL_STATE_RINGING");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(TAG, "CALL_STATE_OFFHOOK");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);
if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){
prev_state=state;
}
if((prev_state==TelephonyManager.CALL_STATE_RINGING)){
prev_state=state;
}
break;
}
}
}
}
Here is my second activity Outcall.Java
public class Outcall1 extends AppCompatActivity {
VideoView myVideo;
private MediaController media_control;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_outcall1);
myVideo = (VideoView) findViewById(R.id.videoView);
Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.myvideo);
media_control = new MediaController(this);
myVideo.setMediaController(media_control);
myVideo.setVideoURI(uri);
myVideo.start();
}
}
There are basically multiple ways for sending broadcasts in android.
In simple terms, some are due to system events such as the all the outgoing calls, while some are private to a particular application i.e the local broadcasts within the app.
1.In your case, the second activity is launching always because your onRecieve() is responding to system events. Hence you should try to sending local broadcast on the button click using the LocalBroadcastManager.sendBroadcast.
Alternatively , you can also use Service for starting your second activity .In this case , before starting call intent start your service .Inside the servie you can set a small delay and then start the second activity.
And for finishing your second activity on call end , you can use the above broadcast reciever that you posted but know for detecting call end, and then in case when the state of phone is call disconnected. Fire another broadcast to be recieved by the second activity which finishes the activity on recieving it.
This will help you with the implementation of the step 2.

How to pass a variable from activities to start a CountDownTimer service?

This is my first question and I've been trying to find a solution to this for hours but can't get it to work. I'm building an android app that takes an input from the user (number of hours) to fast (not eat). The input is then taken to the service where it does a countdown in the background. Along the way, I'd like the user to access other activities that could you the results from the countdown timer (eg, time_left/total_time = percentage complete). So far, my button that I've created works to make the call for the service. but the service never gets called to update the text view. Thanks
Here is what I have,
public class StartFast extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_fast);
startService(new Intent(this, MyService.class));
Log.i("Started service", "hello started service...");
registerReceiver(br, new IntentFilter("COUNTDOWN_UPDATED"));
}
private BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
intent.getExtras();
long millisUntilFinished = intent.getLongExtra("countdown",0);
String time = Long.toString((millisUntilFinished));
TextView tv = findViewById(R.id.timeView1);
tv.setText(time);
}
};
public void BeginFast(View view){
//Intent intent = new Intent( this, StartFast.class);
// below is how to pass an intent for use in a Service to run in the backgroun
Intent intent =new Intent(this, MyService.class);
startService(intent);
// intent.putExtra() // putExtra longs ...will do after static run succeeds
//intent.putExtra("data", data); //adding the data
Intent intent1 = new Intent(this, Heart.class);
startActivity(intent1);
}
}
and here is the service class,
public class MyService extends Service {
private final static String TAG = "MyService";
public static final String COUNTDOWN_BR = "FastBreak.countdown_br";
Intent bi = new Intent(COUNTDOWN_BR);
CountDownTimer cdt = null;
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;
}
}
https://github.com/greenrobot/EventBus
Check this out. This library is the best and easiest implementation of broadcasts. You can send any data to any object (StartFast service in your case) from any other object (StartFast activity in your case) and write code to run.
First, you need to start the service and register it in the manifest. After the service is started by an activity, it will keep running in the background.
You can send intents with a service and anybody who has registered a broadcast receiver listening to that intent can hear it.
Let's say FirstActivity started the service and registers receiver listening to intent with the tag BOBBY. The service is the one sending an intent BOBBY to anyone who is interested and has registered for it.
You want to move on to SecondActivity. Before you do that, onPause of FirstActivity you need to unregister that broadcastreceiver.
SecondActivity is interested in the intent with tag BOBBY, so he creates his own broadcast receiver and registers for it.
I hope you can see where this is going.A broadcastreceiver can listen to all sorts of intents that you make up.
Have fun.

How does a service notify an activity class by sending an object and calling a method from that activity with the sent object?

I am aware of the BroadCastReceiver, but how can I use it to call a method in my activity. So if I get a notification from my service, a button in my UI turns red, and red being the object that has been sent from the service and turning red the method that has been called by the activity.
sorry for bad english :)
Register a BroadcastReceiver in your activity
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
if (message.equals("eventOne"))
{
//do something
}
else if (message.equals("eventTwo"))
{
//do something else
}
}
};
Override onResume and onDestroy of your activity
#Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("my-event"));
}
#Override
protected void onDestroy()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
To check if your service is running add the following on your activity
private static boolean isServiceRunning(String serviceName, Context context)
{
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
if (serviceName.equals(service.service.getClassName()))
{
return true;
}
}
return false;
}
Call it like this
boolean isServiceRunning = isServiceRunning(MyService.class.getName(), this.getApplicationContext());
if (!isServiceRunning)
{
Intent startMyServiceIntent = new Intent(this.getApplicationContext(), MyService.class);
startService(startMyServiceIntent);
}
Finally on your service add a method like that and call it whenever you want
private void sendMessage(String event)
{
Intent intent = new Intent("my-event");
intent.putExtra("message", event);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
sendMessage("eventOne");
return START_STICKY;
}
And don't forget to add your service to manifest
<application
...
...
<service android:name=".MyService"/>
</application>
You can use a BroadcastReceiver, an event bus or an observable. In your activity, listen for the event and call a method that updates your UI how you want.
I do something similarly for GCM intent service. I use an rxBus that posts when the service is triggered. My activity subscribes to the bus and reacts when it sees the post.

Stop/Pause/Sleep Service if connection unavailable and resume if available

I have an application in which I have created a service MyService.class
Now MyService.class is tied to my activity using bindService() but I want my service to run in the background even if activity destroys itself.
So I started the service and then bind it like below:
private void doBindService() {
if (!isServiceBound){
Log.d(LOG_TAG, "Binding Service...");
if (mBtAdapter != null && mBtAdapter.isEnabled()){
Intent intent = new Intent(MyActivity.this, MyService.class);
startService(intent);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
}
In MyActivity's onDestroy method I am unbinding the service
Now my service is running smoothly until the connection with the remote device breaks. I want to pause/sleep/stop this service if connection breaks, then after every 60 seconds it tries to start the service/connection.
I have tried this but doesn't work.
private void stopService() {
doUnbindService();
stopService(new Intent(MyActivity.this, MyService.class));
startService(new Intent(MyActivity.this, MyService.class));
}
Please any help will be much appreciated. Thanks in advance!!!
Try this
create a method that perform the Operation you want
create a Thread or Runnable class
Call the Helper method you created in the run() of the Thread or Runnable
Inside the Service onStartCommand start the Thread if connection is available
thread.wait/sleep if no connection
I'm not sure I have understanding your request.
With this solution you can play, pause and stop service.
And the service do some work every 60seconds
public class MyService extends Service {
public static boolean testConnexion;
private Timer timer;
#Override
public void onCreate() {
super.onCreate();
timer = null;
testConnexion = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (timer != null) {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (testConnexion) {
//StartConnexion
}
}
}, 1000, 60000);
}
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
}
}
In Any activity
To start or stop service.
(Your can call startService many times as you want, there will be just one who will run.)
if (v.getId() == R.id.startService) {
Intent intent = new Intent(this, MyService.class);
startService(intent);
} else if (v.getId() == R.id.stopService) {
Intent intent = new Intent(this, MyService.class);
stopService(intent);
}
To pause action (but not kill the service)
MyService.testConnexion = false;
And for restarting
MyService.testConnexion = true;
Your service is not related to your activity.
If your killing your activity, your service continues to run.
I hope this can help you

Categories