I have 2 areas in my app that launch the default media player on the device and play an audio file (a podcast). One gets it from the file system after a download, the other streams it from the file on the site.
This is working fine right now, problem is if I hit back or home to try and get back to my app after it launches the media player, the player closes and the playback stops.
Is there a way to launch it in the background or as a service so that when I go back to the app, the music keeps playing in the player. I want it to function as if you started a song from the music player. So the user can use the device as normal and the playback will continue.
Here's my code for launching the music player for streaming.
private void playPodcast( Podcast podcast ) {
Intent intent = new Intent( Intent.ACTION_VIEW );
intent.setDataAndType( Uri.parse( podcast.getContentLink() ), "audio/*" );
startActivity( intent );
}
Thanks in advance.
EDIT! After receiving the advice below, I tried launching it as a Service. I've tried this in 2 ways.
Both ways have this as the manifest entry:
<service android:name=".DefaultMusicPlayerLaunchService">
</service>
The first attempt was to make a Service class which was merely a skeleton and launching it with a similar method as above.
DefaultMusicPlayerLaunchService V1:
public class DefaultMusicPlayerLaunchService extends Service {
#Override
public IBinder onBind( Intent intent ) {
// TODO Auto-generated method stub
return null;
}
public int onStartCommand( Intent intent, int flags, int startId ) {
return START_STICKY;
}
}
playPodcast Method:
private void playPodcast( Podcast podcast ) {
Intent intent = new Intent( getApplicationContext(),
DefaultMusicPlayerLaunchService.class );
intent.setDataAndType( Uri.parse( podcast.getContentLink() ), "audio/*" );
startService( intent );
}
My thought was that this way, it would launch the music player similarly to the way it was in the Activity I had before, but launch it without leaving the screen it was on. I didn't see anything happen in the LogCat. I feel like this should work but I'm missing something.
The other method I attempted involved serializing the podcast object as an extra and putting it on the Intent I made for the DefaultMusicPlayerLaunchService. Then, in the onStartCommand method, I grabbed the object, created a new Intent and then called startActivity similarly to how the original playPodcast method at the top does. And as expected, it does just what the top one does... launches the player but as soon as I hit back or home, it closes.
I apologize if I'm missing something obvious. I'm new to Android and everything I've worked with up to now have used Activity. This is my first attempt at starting a Service.
Yes you can start it as a service. You need to create a class that extends android.app.Service. And call startService(intent) from an Activity passing it an intent that will start the service. Override the onStartCommand method and have it return START_STICKY which will have the service run until its explicitly stopped. Either by you in code or by the Android OS to conserve resources. You can also override onBind to bind the service to an Activity which will give the service the same importance as a foreground Activity which makes it less likely that Android will kill the service to save resources.
Related
I've been facing a problem for a while regarding startActivity(intent). What i'm developing is a kind of key word detection like "ok google" that triggers an alert when the user says the word. To achieve that when the user is not using the app i have a LifecycleService that runs in foreground and listens to the user. When the user says the word and the app is killed it opens the activity i need using startActivity from the service, but the problem is that if i keep listening and change to other activity (using the app normally) the detection works (because i hear the sound i put when the word is recognized) but the app doesn't start the activity it should (although the startActivity(intent) is called). I'm pretty sure that the problem has to be with the context that maybe is not the correct one when i open the app with startActivity from the service, but i don't know how to fix it. I tried to user some other variables like applicationContext or the androidContext() from Koin but it is not working.
class SpeechRecognitionService : LifecycleService() {
...
//onStartCommand starts the audio recognizer and startAlert() is triggered when the alert is recognized. It is always correctly called
private fun startAlert() {
//This is not showing MainActivity although i execute it
startActivity(MainActivity.getDialogIntent(this))
//I always hear this audio when the app detects word
val audio = MediaPlayer.create(this, R.raw.alert_detected_audio)
audio.start()
}
}
The MainActivity.getDialogIntent(this) is just a common Intent
fun getDialogIntent(context: Context): Intent {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.putExtra(SHOW_ALERT_DIALOG_KEY, true)
return intent
}
The problem only happens if the app is started with the voice recognition (after being killed). If i for example kill the app but open the app again pressing the app icon it works correctly. If i start the app with voice (so, from the startActivity i have above) i worked that time and open the app but when i change to other activity it fails to start.
You need to use a proper "launcher Intent". The easiest way to get one is to call
PackageManager pm = getPackageManager()
Intent intent = pm.getLaunchIntentForPackage("my.package.name")
Use this Intent to start your MainActivity instead of calling MainActivity.getDialogIntent(this)
Thanks in advance for the help.
I have an app that can be started by either the user physically starting the app (like you would any normal app) or by a repeating service. Depending on what starts the app (the user or the service) I want to preform different initialization actions. How might I be able to detect if an user starts the app without doing anything custom (I imagine that there has to be some kind of built in setting in android for me to determine this)?
If service, that starts your Activity, is yours service, you can put some custom information (using Intent#putExtra for example) in Intent you use to start Activity from Service.
In Activity you can use Activity#getIntent(), that returns the intent that started this activity.
If you started Activity from Service, that Intent will be the one you passed in Service#startActivity, and will have your custom information. Otherwise, that was not your Service, that started your Activity.
That could look somehow like that, for example:
//in Activity
public static final String EXTRA_STARTED_FROM_MY_SERVICE = "com.example.extra_started_from_sevice";
private boolean wasActivityStartedFromService() {
Intent startingIntent = getIntent();
//assuming you will use Intent#putExtra in your service when starting activity
return startingIntent.getBooleanExtra(EXTRA_STARTED_FROM_MY_SERVICE, false);
}
//...
//in Service
//...
Intent startingIntent = new Intent(this, MainActivity.class);
startingIntent.putExtra(MainActivity.EXTRA_STARTED_FROM_MY_SERVICE, true);
startActivity(startingIntent);
I'm starting to make an Android app that stream music from a radio station. So i have an activity which retrieve the info about the artist, title and the cover of the album. And also everything which about the UI (play, pause, Quit and change the bandwidth). Everything works fine when i first launch the app but when i pressed the home button and i relaunch the application Android recreate the activity (by passing by onResume etc). But my service with the musicPlayer continues to play and then i cannot send instructions from the activity because the activity can't access to the Service.
So my question is when the activity is recreate with onResume etc how can we sends informations to the service.
Here's how i create the service and sends information to it:
onCreate(){
...
Intent intent = new Intent(getApplicationContext(), Play.class);
intent.putExtra("play", true);
intent.putExtra("pause", false);
intent.putExtra("stop", false);
intent.putExtra("artist", artist);
intent.putExtra("title", title);
intent.putExtra("speed", "low");
intent.putExtra("restart", restart);
startService(intent);
restart = false;
...
}
I saw that there's exist onBind() function but i'm not sure how it's works neither if it's this that i'm needed.
Thank you in advance
P.S. Hope my english isn't too bad
We have a live video streaming app with a lot going on. A user presses the home button. I want the app to be removed from memory. When the app is selected again we have a brand new load. There are a lot of processes going on and we don't want to have to manually manage all the connections, streams, etc. This is how our iPhone version of the app works.
I've read this: Is quitting an application frowned upon?
I don't really care about Androids design patterns here either way. However if someone has an elegant, simple way that all my activities will be removed from the stack when the home button is pressed, and then when the app is reloaded it starts with a fresh main activity, that would be great. Also, I can't seem to ever debug when the home key is pressed in onKeyDown. Its simply not registering. (keyCode == KeyEvent.KEYCODE_HOME) is my check. It picks up back buttons, etc.
Any thoughts?
You can call system.exit(0); but I would still suggest to follow the Android guidelines, and clean everything (as should be) on onPause() or similar method.
Could you just override the onPause method and use the finish() function?
int p = android.os.Process.myPid();
android.os.Process.killProcess(p);
you can do than on button click. Define any static method like exit() and define
android.os.Process.killProcess(android.os.Process.myPid()); in exit method
in the main or first activity.
Then call this method on button click.
If you want to clear all of your activities from the stack, you can broadcast an intent from the activity which initiates the quit like this:
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("CLEAR_STACK");
sendBroadcast(broadcastIntent);
And in every one of your activities that you want to be cleared off the stack you can create a BroadcastReceiver with an inner class:
class ActivitiesBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
}
And register your BroadcastReceiver in the onCreate() method:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("CLEAR_STACK");
BroadcastReceiver r;
r = new ActivitiesBroadcastReceiver();
registerReceiver(r, intentFilter);
I'd like to launch a video capture Intent that calls me back with some kind of result. So far it correctly launches the G1's default Camcorder app, but when I finish recording the video in Camcorder, it just sits there (still in the Camcorder app) instead of calling my onActivityResult() method.
Is this just a shortcoming of Camcorder, or is there a special flag or extra I can set to tell it to return control when it's done recording? Ideally it would pass me back a handle to the video - a URI, an InputStream, a file path.
The code:
protected void launchRecordVideoActivity() {
Intent intent = new Intent (android.provider.MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult (intent, RequestCodes.RECORD_VIDEO);
}
RequestCodes is my own interface containing int constants.
public void onActivityResult (int requestCode, int resultCode, Intent intent) {
...
}
The contents of onActivityResult don't matter because my app is never called back at all.
onActivityResult is not being called.
Any suggestions? I can also bake the video recording directly into the app, but I'd prefer not to.
You can't (generally) call startActivityForResult on an intent that starts an application outside of your application
Same code works fine on SE x10 (updated to sdk 2.1). Activity starts, user starts recording video and when he press stop - video onActivityResult() is run in calling class.
Probably it was fixed in later SDK releases.