starting an activity stops android service - java

i have an android service that plays music.i start in my main activity with this code:
Intent service = new Intent(MainMenu.this, musicservice.class);
MainMenu.this.startService(service);
and this is my service:
public class musicservice extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
MediaPlayer mp;
mp = MediaPlayer.create(musicservice.this, R.raw.music);
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
mp.start();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
it stsrts work fine, but when i start another activity, my music goes off and seems my service destroys!! but dont want this, i want my service only stops when my application ends. music plays only when user works with app. even when app in in the background i want my music dont play! how i can implement this?

If you want your application to play music while your activity is on, try bind it.
it should look something like this:
Service:
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.IBinder;
import com.example.playmusic.R;
public class PlayMusicService extends Service {
private final IBinder binder = new LocalBinder();
private MediaPlayer player;
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public class LocalBinder extends Binder {
public PlayMusicService getService() {
return PlayMusicService.this;
}
}
public void play() {
player = MediaPlayer.create(this, R.raw.music);
player.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
player.start();
}
public void pause() {
player.pause();
}
}
Activity:
package com.example.playmusic;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import com.example.service.PlayMusicService;
import com.example.service.PlayMusicService.LocalBinder;
public class MainActivity extends Activity {
private PlayMusicService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onPause() {
super.onPause();
service.pause();
}
#Override
protected void onStart() {
super.onStart();
if (service != null) {
service.play();
} else {
bindService();
}
}
private void bindService() {
bindService(new Intent(this, PlayMusicService.class), new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
LocalBinder localBinder = (LocalBinder) binder;
service = localBinder.getService();
service.play();
}
}, Context.BIND_AUTO_CREATE);
}
}

Service destroy when your activity destroy when you start service from activity.
Use AlarmManager to schedule the service repeatedly.

Related

Android wear OS retrieving stepcounter in background

I am trying to retrieve step counts from a smartwatch and push it to API. I was able to retrieve and push the data when I open the app. But once it is not activated, then it will not send any data. I am trying to use the android service to run the app in the background so that it will send the data continuously. I have given all the permissions and enabled them.
This is MainActivity.java
package com.example.stepcounter;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
protected void onResume() {
super.onResume();
}
protected void onPause() {
super.onPause();
}
protected void onDestroy() {
super.onDestroy();
}
public void onPressStartService(View v){
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
public void onPressStopService(View v){
stopService(new Intent(getApplicationContext(), MyService.class));
}
}
And this is MyService.java
package com.example.stepcounter;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
public class MyService extends Service implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
private String HelloData;
private TextView mTextView;
private boolean isSensorPresent;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mSensorManager = (SensorManager)this.getSystemService(Context.SENSOR_SERVICE);
if(mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE) != null) {
mSensor = mSensorManager.getDefaultSensor(69680);
isSensorPresent = true;
} else {
isSensorPresent = false;
}
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onSensorChanged(SensorEvent event) {
mTextView.setText("Heart Rate: " + String.valueOf(event.values[0]));
HelloData = (String) String.valueOf(event.values[0]);
if(!HelloData.contains("0.0")){
postDataUsingVolley(HelloData);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private void postDataUsingVolley(String ranData) {
String url = "https://test.com";
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject postData = new JSONObject();
try {
postData.put("data", ranData);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, postData, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
queue.add(jsonObjectRequest);
}
}
I have also added the following in AndroidManifest.xml
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
It works for 30 seconds, send the data and once the watch goes inactive, it stops sending data. Any idea what is wrong with this?
You need to unregister your Sensor during onPause:
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
Also, if you unregister, you need to use your boolean activityRunning.

Losing state of the activity when navigating from notification to activity

I have an activity named Player Activity in which I am streaming music with the help of MediaPlayer API. Whenever my activity is created a notification is displayed which has some basic control of the music player.
So when I tap on my notification it jumps back to the Player Activity, but the state of the activity is lost.
Before tapping on notification :
After tapping on notification :
Here is the code of my notification's Pending Intent
Intent notifyIntent = new Intent(context, PlayerActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
notifyIntent.setAction("android.intent.action.MAIN");
notifyIntent.addCategory("android.intent.category.LAUNCHER");
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Here is the code for PlayerActivity.java :
package com.example.user.musicplayer;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import java.util.concurrent.TimeUnit;
import de.hdodenhof.circleimageview.CircleImageView;
public class PlayerActivity extends AppCompatActivity implements MediaPlayer.OnBufferingUpdateListener,MediaPlayer.OnCompletionListener{
private static Button btn_play_pause;
private Button btnToggleRepeat;
private Button btnStop;
private SeekBar seekBar;
private TextView textView;
public static MediaPlayer mediaPlayer;
private int mediaFileLength;
private int realtimeLength;
private String musicUrl;
private String imageUrl;
final Handler handler = new Handler();
private boolean isRepeat;
private CircleImageView musicImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
Log.d("TAG", "onCreate");
NotificationGenerator.customBigNotification(getApplicationContext());
musicUrl = getIntent().getStringExtra("musicUrl");
imageUrl = getIntent().getStringExtra("imageUrl");
seekBar = (SeekBar)findViewById(R.id.seekbar);
seekBar.setMax(99); // 100% (0~99)
seekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(mediaPlayer.isPlaying())
{
SeekBar seekBar = (SeekBar)v;
int playPosition = (mediaFileLength/100)*seekBar.getProgress();
mediaPlayer.seekTo(playPosition);
}
return false;
}
});
textView = (TextView)findViewById(R.id.txtTime);
btnToggleRepeat = findViewById(R.id.btnRepeat);
btnStop = findViewById(R.id.btnStop);
musicImage = findViewById(R.id.musicImgView);
Picasso.get().load(imageUrl).placeholder(R.drawable.music).error(R.drawable.music).into(musicImage);
btn_play_pause = (Button) findViewById(R.id.btnTogglePlay);
btn_play_pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final ProgressDialog mDialog = new ProgressDialog(PlayerActivity.this);
AsyncTask<String,String,String> mp3Play = new AsyncTask<String, String, String>() {
#Override
protected void onPreExecute() {
mDialog.setMessage("Please wait");
mDialog.show();
}
#Override
protected String doInBackground(String... params) {
try{
mediaPlayer.setDataSource(params[0]);
mediaPlayer.prepare();
}
catch (Exception ex)
{
}
return "";
}
#Override
protected void onPostExecute(String s) {
mediaFileLength = mediaPlayer.getDuration();
realtimeLength = mediaFileLength;
if(!mediaPlayer.isPlaying())
{
playMusic();
}
else
{
pauseMusic();
}
updateSeekBar();
mDialog.dismiss();
}
};
mp3Play.execute(musicUrl); // direct link mp3 file
}
});
btnToggleRepeat.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isRepeat){
isRepeat = false;
mediaPlayer.setLooping(false);
btnToggleRepeat.setText("Repeat");
}
else{
isRepeat = true;
mediaPlayer.setLooping(true);
btnToggleRepeat.setText("Single");
}
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
mediaPlayer.pause();
mediaPlayer.stop();
}
catch (Exception e){
Toast.makeText(PlayerActivity.this, "Opps! sorry something bad happened", Toast.LENGTH_SHORT).show();
}
}
});
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
public void pauseMusic() {
mediaPlayer.pause();
btn_play_pause.setText("Play");
}
public void playMusic() {
mediaPlayer.start();
btn_play_pause.setText("Pause");
}
private void updateSeekBar() {
seekBar.setProgress((int)(((float)mediaPlayer.getCurrentPosition() / mediaFileLength)*100));
if(mediaPlayer.isPlaying())
{
Runnable updater = new Runnable() {
#Override
public void run() {
updateSeekBar();
realtimeLength-=1000; // declare 1 second
textView.setText(String.format("%d:%d",TimeUnit.MILLISECONDS.toMinutes(realtimeLength),
TimeUnit.MILLISECONDS.toSeconds(realtimeLength) -
TimeUnit.MILLISECONDS.toSeconds(TimeUnit.MILLISECONDS.toMinutes(realtimeLength))));
}
};
handler.postDelayed(updater,1000); // 1 second
}
}
#Override
protected void onResume() {
super.onResume();
Log.d("TAG", "onResume");
}
#Override
protected void onStart() {
super.onStart();
Log.d("TAG", "onStart");
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
seekBar.setSecondaryProgress(percent);
}
#Override
public void onCompletion(MediaPlayer mp) {
if(!mediaPlayer.isLooping())
btn_play_pause.setText("Play");
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onPause() {
super.onPause();
}
public static class DownloadCancelReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("notificationPlayer","Received Cancelled Event");
}
}
}
Thanks in advance. Pardon me if the explanation is not clear, because if i might have right words to explain it, I would have googled it.
Add this to your PlayerActivity activity in manifest :
android:launchMode="singleTask"
And use these flags in the intent for pendingintent :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

Error: View cannot be applied to Intent

I'm new to Android App Development and creating a simple service app. It has a button to start service and a button to stop service with their repective methods. Following is my code:
App3_main.java
package eg.app3;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class App3_main extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app3_main);
}
public void startservice(View view)
{
Intent intent = new Intent(this,MyService.class);
startservice(intent); //this is where I'm getting the error mentioned in the title
}
public void stopservice(View view)
{
Intent intent = new Intent(this,MyService.class);
stopservice(intent); //this is where I'm getting the error mentioned in the title
}
}
MyService.java
package eg.app3;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
public MyService() {
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this,"Service Started",Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
Toast.makeText(this,"Service Stopped",Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Please guide me where I'm wrong.
Replace:
startservice(intent);
with:
startService(intent);
Then, replace:
stopservice(intent);
with:
stopService(intent);
Like most programming languages, Java is case-sensitive.

Creating notification once onSensorChanged method is called Android

This is the myService class:
package me.smarthwatches.simplenotification;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service implements SensorEventListener {
private static final String DEBUG_TAG = "AccelLoggerService";
private SensorManager mSensorManager;
private Sensor mSensor;
// on start command: register listener, on create:, and on destroy, Ibinder return null
//get the system service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
// return super.onStartCommand(intent, flags, startId);
return START_STICKY; // want service to continue running until its explicitly stopped so return sticky
}
#Override
public void onCreate() {
// super.onCreate();
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onDestroy() {
// super.onDestroy();
mSensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
return;
}
#Override
public void onSensorChanged(SensorEvent event) {
if (Math.abs(event.values[0]) > 9.8 || Math.abs(event.values[1]) > 9.8 || Math.abs(event.values[2]) > 9.8) {
Log.v(MyService.DEBUG_TAG, "value is greater than 9");
//need to launch a notification? ask if person is excited?
showNotification();
}
mSensorManager.unregisterListener(this);
}
/** Notification to show person is excited */
private void showNotification() {
// create a button here asking if excited
Notification notification = new NotificationCompat.Builder(getApplication())
.setContentTitle("Excited")
.setContentText("Well are you?")
.extend(
new NotificationCompat.WearableExtender().setHintShowBackgroundOnly(true))
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplication());
int notificationId = 2;
notificationManager.notify(notificationId, notification);
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return null;
}
}
This is the WearActivity Class:
package me.smarthwatches.simplenotification;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.wearable.view.WatchViewStub;
import android.widget.TextView;
public class WearActivity extends Activity {
private TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wear);
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
#Override
public void onLayoutInflated(WatchViewStub stub) {
mTextView = (TextView) stub.findViewById(R.id.text);
}
});
Intent serviceIntent = new Intent(getApplicationContext(), MyService.class);
startService(serviceIntent);
}
Essentially, what I'd like to do is that once the accelerometer, which is running on a service in the background, reaches a certain threshold (9.8), then I want to display something to the screen for the Wear Activity. I'd like a notification that says "Are you excited?", and want it to do something when I click on it. First, I'm not sure how to even add the notification here, and second I'm not sure if I add it to the service class in showNotification() method that I made up, or just say somehow if I pass the threshold, go to the mainactivity and display a button?
UPDATE: I've added my showNotification method, but not sure why it doesn't do anything. I printed a log statement for onSensorChanged() and I see it showing up in the LogCat so it is entering that method. Not sure how to make it show this notification though.

Implementing Music Across Activities

Problem: When I use the home button to close the app the music continues playing. So I manually close the app by killing the activity, the music stops... for a few seconds and then starts again (and this time a restart is in order to turn it off).
MusicService.class:
package com.MyApp.App;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class MusicService extends Service implements
MediaPlayer.OnErrorListener {
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public MusicService() {
}
public class ServiceBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
mPlayer = MediaPlayer.create(this, R.raw.test_music);
mPlayer.setOnErrorListener(this);
if (mPlayer != null) {
mPlayer.setLooping(true);
mPlayer.setVolume(100, 100);
}
mPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
onError(mPlayer, what, extra);
return true;
}
});
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mPlayer.start();
return START_STICKY;
}
public void pauseMusic() {
if (mPlayer.isPlaying()) {
mPlayer.pause();
length = mPlayer.getCurrentPosition();
}
}
public void resumeMusic() {
if (mPlayer.isPlaying() == false) {
mPlayer.seekTo(length);
mPlayer.start();
}
}
public void stopMusic() {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mPlayer != null) {
try {
mPlayer.stop();
mPlayer.release();
} finally {
mPlayer = null;
}
}
}
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "music player failed", Toast.LENGTH_SHORT).show();
if (mPlayer != null) {
try {
mPlayer.stop();
mPlayer.release();
} finally {
mPlayer = null;
}
}
return false;
}
}
MainPage.class:
package com.MyApp.App;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
public class MainPage extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
Intent music = new Intent();
music.setClass(this, MusicService.class);
startService(music);
}
#Override
protected void onDestroy() {
super.onDestroy();
mServ.stopMusic();
}
#Override
protected void onPause() {
super.onPause();
mServ.pauseMusic();
}
#Override
protected void onStop() {
super.onStop();
mServ.stopMusic();
}
private boolean mIsBound = false;
private MusicService mServ;
private ServiceConnection Scon = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder) {
mServ = ((MusicService.ServiceBinder) binder).getService();
}
public void onServiceDisconnected(ComponentName name) {
mServ = null;
}
};
void doBindService() {
bindService(new Intent(this, MusicService.class), Scon,
Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
unbindService(Scon);
mIsBound = false;
}
}
}
(NOTE: I have taken excerpts from my app, so I may have forgotten imports in this code, but all imports are correctly included in the app.)
Fixed:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
doBindService();
Intent music = new Intent();
music.setClass(this, MusicService.class);
startService(music);
}
and
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
please red : onCreate, OnPause , OnResume

Categories