Start Android TTS from Broadcast Receiver or Service - android

I'm trying to get TTS to run in the background. But, I never get any sound. I have a broadcast receiver which starts a service. I put my TTS code in both of those, but it never speaks. I know the method is being called (I put a breakpoint on it), but it still doesn't work.
Here's my log, but it doesn't seem to contain anything about the TTS service.
10-04 22:45:30.663: WARN/InputManagerService(209): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy#4423df40
10-04 22:45:37.363: INFO/PollingManager(449): calculateShortestInterval(): shortest interval is 540000
10-04 22:45:37.413: INFO/TLSStateManager(449): org.apache.harmony.nio.internal.SocketChannelImpl#4400ece0: Wrote out 29 bytes of data with 0 bytes remaining.
10-04 22:45:38.043: ERROR/IMAPEmailService(480): Can't create default IMAP system folder Trash. Please reconfigure the folder names.
10-04 22:45:40.123: ERROR/EONS(303): EF_PNN: No short Name
10-04 22:45:41.543: ERROR/WMSTS(171): Month is invalid: 0
10-04 22:45:42.043: WARN/AudioFlinger(172): write blocked for 212 msecs, 24 delayed writes, thread 0xb998
Thanks everyone in advance!

It would help to see your TTS code to make it easier for people to help you. Since I already have TTS working in a BroadcastReceiver, here's an example trimmed down from my code.
public static class TTS extends Service implements TextToSpeech.OnInitListener, OnUtteranceCompletedListener {
private TextToSpeech mTts;
private String spokenText;
#Override
public void onCreate() {
mTts = new TextToSpeech(this, this);
// This is a good place to set spokenText
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = mTts.setLanguage(Locale.US);
if (result != TextToSpeech.LANG_MISSING_DATA && result != TextToSpeech.LANG_NOT_SUPPORTED) {
mTts.speak(spokenText, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
#Override
public void onUtteranceCompleted(String uttId) {
stopSelf();
}
#Override
public void onDestroy() {
if (mTts != null) {
mTts.stop();
mTts.shutdown();
}
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
Start the TTS service at the point in your BroadcastReceiver where you want it to speak:
context.startService(new Intent(context, TTS.class));
I hope this helps someone if not the asker (I'm sure he got it working by now).

you can also try this,if the text to be spoken is coming from a broadcast listener.first create a service
public class MyTell extends Service implements OnInitListener{
public MyTell() {
}
public static TextToSpeech mTts;
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
mPreferences = getSharedPreferences(Mysettings.PREF_NAME, Service.MODE_PRIVATE);
pit = Float.parseFloat(mPreferences.getString("pit","0.8"));
rate = Float.parseFloat(mPreferences.getString("rate","1.1"));
mTts = new TextToSpeech(this, this);
super.onStart(intent, startId);
}
public void onInit(int status) {
// TODO Auto-generated method stub
if (status == TextToSpeech.SUCCESS) {
if (mTts.isLanguageAvailable(Locale.UK) >= 0)
Toast.makeText( MyTell.this,
"Sucessfull intialization of Text-To-Speech engine Mytell ",
Toast.LENGTH_LONG).show();
mTts.setLanguage(Locale.UK);
mTts.setPitch(pit);
mTts.setSpeechRate(rate);
} else if (status == TextToSpeech.ERROR) {
Toast.makeText(MyTell.this,
"Unable to initialize Text-To-Speech engine",
Toast.LENGTH_LONG).show();
}
}}
then create the listener where you're insert your text
public class MyBroadCast extends BroadcastReceiver {
public MyPop() {
}
#Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//here is where you're use the service you created to speak the text
MyTell.mTts.speak("Text to be spoken", TextToSpeech.QUEUE_FLUSH,null);
}
}
make sure you start the service before you use the tts engine and also check if a tts engine is available

Its working for me (just add on mainfest permision)
public class TES extends Service implements TextToSpeech.OnInitListener {
private TextToSpeech tts;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
tts = new TextToSpeech(this, this);
speakOut();
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
}
speakOut();
} else {
Log.e("TTS", "Initilization Failed!");
}
}
private void speakOut() {
tts.speak("its working", TextToSpeech.QUEUE_FLUSH, null);
}
}

Android TTS is a bounded service. Broadcast receiver has a limited context and can't bind himself to any service. However, It can START a service. All the examples shown here are of services that starting the TTS engine and of receiver that starts them.
You can also do it with activity but if you don't need UI a service is better.
I just think it's a good idea to understand how it works and why is works.
Good luck.

Using Kotlin, the above answers can be re-written as:
Receiver:
class MyReceiver : BroadcastReceiver() {
val ttsService = Intent(context, TTS::class.java)
context.startService(ttsService)
}
Service:
class TTS : Service(), TextToSpeech.OnInitListener {
private var mTts: TextToSpeech? = null
private var spokenText: String? = null
override fun onCreate() {
mTts = TextToSpeech(this, this)
// This is a good place to set spokenText
spokenText = "Hello!.."
}
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
val result = mTts!!.setLanguage(Locale.US)
if (result != TextToSpeech.LANG_MISSING_DATA && result != TextToSpeech.LANG_NOT_SUPPORTED) {
Thread().run {
mTts!!.apply {
speak(spokenText, TextToSpeech.QUEUE_FLUSH, null, null)
}
Thread.sleep(10000)
stopSelf()
}
}
} else if (status == TextToSpeech.ERROR) {
stopSelf()
}
}
override fun onDestroy() {
if (mTts != null) {
mTts!!.stop()
mTts!!.shutdown()
}
super.onDestroy()
}
override fun onBind(arg0: Intent): IBinder? {
return null
}
}
And in the Manifest:
<receiver
android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.xxxx" />
</intent-filter>
</receiver>
<service android:name=".TTS" />

Android-O onwards using service for things like this has background restrictions. One can use JobIntentService to achieve the same as shown here.

Related

Big issue with android.content.Context.getSystemService(java.lang.String)' on a null object reference error [duplicate]

This question already has answers here:
Service crashes with nullpointerexception at onCreate
(2 answers)
Cant run background service
(3 answers)
Closed 4 years ago.
I'm trying to build a music app in Android, although I feel ridiculously newbie sometimes. I have researched a lot, tried my best at getting the hang of how MediaPlayer, MediaBrowserCompat / MediaBrowserServiceCompat, MediaController and Services work, tens of unfortunately old tutorials about how to build one.
My biggest issue was that most of them tended to use the IBinder functionality and intents to bind and start the musicPlaybackService, while google's documentation used these MediaBrowser and MediaBrowserService APIs, both approaches new and honestly quite hard and overwhelming for me.
I've learned a lot so far, but it was hard. The two slightly better tutorials I've found are
https://www.sitepoint.com/a-step-by-step-guide-to-building-an-android-audio-player-app/, and https://code.tutsplus.com/tutorials/background-audio-in-android-with-mediasessioncompat--cms-27030 and they use the first and the second approach. My version of the app is what I managed to make by putting together all the pieces I've learned.
A lot of bugs and issues I managed to figure out on my own, but I've encountered a NullPointer exception that I simply don't know how to solve. The debugger is weird as well on this one, it feels almost like every time the error comes from another place of the program; sometimes it stops at the breakpoints I put, and then running the debugger again with the exact same code and breakpoints, it skips them and goes straight into the Runtime error.
This is my Manifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ecebuc.gesmediaplayer">
<permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MediaPlaybackService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
</application>
Then this is my MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private final int REQUEST_CODE_GESPLAYER_EXTERNAL_STORAGE = 101;
private static final int STATE_PAUSED = 0;
private static final int STATE_PLAYING = 1;
private static int currentState;
private MediaBrowserCompat gesMediaBrowser;
private MediaControllerCompat gesMediaController;
public MediaControllerCompat.TransportControls gesPlaybackController;
private Button playPauseToggleButton;
private MediaBrowserCompat.ConnectionCallback mediaBrowserCallbacks = new MediaBrowserCompat.ConnectionCallback() {
#Override
public void onConnected() {
super.onConnected();
try {
//create the media controller and register the callbacks to stay in sync
gesMediaController = new MediaControllerCompat(MainActivity.this, gesMediaBrowser.getSessionToken());
gesMediaController.registerCallback(mediaControllerCallbacks);
//save the controller and define the easy access transport controls in the object
MediaControllerCompat.setMediaController(MainActivity.this, gesMediaController);
gesPlaybackController = gesMediaController.getTransportControls();
//Display initial state
MediaMetadataCompat metadata = gesMediaController.getMetadata();
PlaybackStateCompat pbState = gesMediaController.getPlaybackState();
} catch( RemoteException e ) {
}
}
#Override
public void onConnectionSuspended() {
// The Service has crashed. Disable transport controls until it automatically reconnects
}
#Override
public void onConnectionFailed() {
// The Service has refused our connection
Log.d("onConnectionFail: ", "the service hasn't been able to connect");
}
};
private MediaControllerCompat.Callback mediaControllerCallbacks = new MediaControllerCompat.Callback() {
#Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
super.onMetadataChanged(metadata);
}
#Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
super.onPlaybackStateChanged(state);
if( state == null ) {
Log.d("onPlaybackChange: ", "the state is null");
Toast.makeText(MainActivity.this,
"onPlaybackStateChange: the state is null",
Toast.LENGTH_SHORT)
.show();
return;
}
switch( state.getState() ) {
case PlaybackStateCompat.STATE_PLAYING: {
currentState = STATE_PLAYING;
break;
}
case PlaybackStateCompat.STATE_PAUSED: {
currentState = STATE_PAUSED;
break;
}
}
}
#Override
public void onSessionDestroyed(){
// Override to handle the session being destroyed
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//grab the buttons for media playback control
playPauseToggleButton = (Button)findViewById(R.id.playPause_btn);
//request permissions for external storage
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission have not been granted
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_CODE_GESPLAYER_EXTERNAL_STORAGE);
}
else{
//permissions have already been granted
}
//initiate connection to the MediaPlaybackService through MediaBrowser
gesMediaBrowser = new MediaBrowserCompat(this,
new ComponentName(this, MediaPlaybackService.class),
mediaBrowserCallbacks, getIntent().getExtras());
gesMediaBrowser.connect();
//Attach listeners to them
playPauseToggleButton.setOnClickListener(this);
// space here for other buttons
// sapce here for other buttons
}
#Override
protected void onStart() {
super.onStart();
//gesMediaBrowser.connect();
}
/*protected void onStop() {
super.onStop();
// (see "stay in sync with the MediaSession")
if( gesMediaController.getPlaybackState().getState() == PlaybackStateCompat.STATE_PLAYING ) {
gesPlaybackController.pause();
}
gesMediaBrowser.disconnect();
}*/
#Override
protected void onDestroy() {
super.onDestroy();
/*if (gesMediaController != null) {
gesMediaController.unregisterCallback(mediaControllerCallbacks);
gesMediaController = null;
}
if(gesMediaBrowser != null && gesMediaBrowser.isConnected()) {
gesMediaBrowser.disconnect();
gesMediaBrowser = null;
}*/
if( gesMediaController.getPlaybackState().getState() == PlaybackStateCompat.STATE_PLAYING ) {
gesPlaybackController.pause();
}
gesMediaBrowser.disconnect();
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.playPause_btn:
//has to be dealt with accordingly, based on the current state of mediaplayer
int currentState = gesMediaController.getPlaybackState().getState();
if(currentState == PlaybackStateCompat.STATE_PLAYING) {
gesPlaybackController.pause();
} else {
//gesPlaybackController.play();
gesPlaybackController.playFromMediaId(String.valueOf(R.raw.warner_tautz_off_broadway), null);
}
break;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_GESPLAYER_EXTERNAL_STORAGE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "onRequestPermissionResult: granted", Toast.LENGTH_SHORT).show();
} else {
//close the app if permissions aren't granted
//Toast.makeText(this, "onRequestPermissionResult: denied", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
And then the playbackService.java
public class MediaPlaybackService extends MediaBrowserServiceCompat implements
MediaPlayer.OnCompletionListener,
AudioManager.OnAudioFocusChangeListener {
public static final String COMMAND_EXAMPLE = "command_example";
public static boolean isServiceStarted = false;
/*public int audioIndex;
public ArrayList<Audio> audioList;
public Audio activeAudio;*/
private MediaPlayer gesMediaPlayer;
private MediaSessionCompat gesMediaSession;
private int pausedPosition;
//-------------------------------------Lifecycle methods--------------------------------------//
#Override
public void onCreate() {
super.onCreate();
Log.d("onCreate: ", "Service created");
initMediaPlayer();
initMediaSession();
callStateListener();
registerNoisyReceiver();
// Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player
PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY |
PlaybackStateCompat.ACTION_PLAY_PAUSE);
gesMediaSession.setPlaybackState(playbackStateBuilder.build());
}
#Override
public void onDestroy() {
super.onDestroy();
if (gesMediaPlayer != null) {
gesMediaPlayer.stop();
gesMediaPlayer.release();
}
//Disable the PhoneStateListener
if (phoneStateListener != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}
removeAudioFocus();
unregisterReceiver(becomingNoisyReceiver);
//clear cached playlist
//new StorageUtils(getApplicationContext()).clearCachedAudioPlaylist();
NotificationManagerCompat.from(this).cancel(1);
stopSelf();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("onStartCommand: ", "Service has been started");
MediaButtonReceiver.handleIntent(gesMediaSession, intent);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
if( gesMediaPlayer != null ) {
gesMediaPlayer.release();
}
}
//----------------------------------------Initialisers----------------------------------------//
private void initMediaPlayer() {
gesMediaPlayer = new MediaPlayer();
gesMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
gesMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
gesMediaPlayer.setVolume(1.0f, 1.0f);
/*try {
//sets songPath as data source for media player
//gesMediaPlayer.setDataSource(songPath);
//sets current song as data source for media player
gesMediaPlayer.setDataSource(activeAudio.getData());
} catch (IOException e) {
e.printStackTrace();
stopSelf();
}
gesMediaPlayer.prepareAsync();*/
}
private void initMediaSession() {
ComponentName mediaButtonReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class);
gesMediaSession = new MediaSessionCompat(getApplicationContext(), "GESMediaService",
mediaButtonReceiver, null);
gesMediaSession.setCallback(mediaSessionCallbacks);
gesMediaSession.setFlags( MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS );
//this is for pre-Lollipop media button handling on those devices
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setClass(this, MediaButtonReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0);
gesMediaSession.setMediaButtonReceiver(pendingIntent);
// Set the session's token so that client activities can communicate with it.
setSessionToken(gesMediaSession.getSessionToken());
}
private void registerNoisyReceiver() {
//Handles headphones coming unplugged. cannot be done through a manifest receiver
IntentFilter noisyFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(becomingNoisyReceiver, noisyFilter);
}
private void initMediaSessionMetadata() {
MediaMetadataCompat.Builder metadataBuilder = new MediaMetadataCompat.Builder();
//Notification icon in card
metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
//lock screen icon for pre lollipop
metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Display Title");
metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Display Subtitle");
metadataBuilder.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, 1);
metadataBuilder.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, 1);
gesMediaSession.setMetadata(metadataBuilder.build());
}
//-----------------------------------Media Playback functions---------------------------------//
//TODO: read about the AssetFileDescriptor, and the ResultReceiver
private MediaSessionCompat.Callback mediaSessionCallbacks = new MediaSessionCompat.Callback() {
#Override
public void onPlay() {
super.onPlay();
if(!requestAudioFocus()) {
//failed to gain focus
return;
}
//check if service is started, not only bound
if(!isServiceStarted){
startService(new Intent(getApplicationContext(), MediaPlaybackService.class));
}
gesMediaSession.setActive(true);
setMediaPlaybackState(PlaybackStateCompat.STATE_PLAYING);
showPlayingNotification();
gesMediaPlayer.start();
}
#Override
public void onPause() {
super.onPause();
if( gesMediaPlayer.isPlaying() ) {
gesMediaPlayer.pause();
setMediaPlaybackState(PlaybackStateCompat.STATE_PAUSED);
showPausedNotification();
}
}
#Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
super.onPlayFromMediaId(mediaId, extras);
try {
AssetFileDescriptor afd = getResources().openRawResourceFd(Integer.valueOf(mediaId));
if( afd == null ) {
Log.d("afd: ", "afd in onPlayFromMediaId is null");
return;
}
try {
gesMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch( IllegalStateException e ) {
gesMediaPlayer.release();
initMediaPlayer();
gesMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
}
afd.close();
initMediaSessionMetadata();
} catch (IOException e) {
e.printStackTrace();
return;
}
try {
gesMediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
Log.d("onPlayFromId: ", "mediaPlayer failed to prepare");
}
//Work with extras here if you want
}
#Override
public void onCommand(String command, Bundle extras, ResultReceiver cb) {
super.onCommand(command, extras, cb);
if( COMMAND_EXAMPLE.equalsIgnoreCase(command) ) {
//Custom command here
}
}
#Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
}
};
private void setMediaPlaybackState(int state) {
PlaybackStateCompat.Builder playbackstateBuilder = new PlaybackStateCompat.Builder();
if( state == PlaybackStateCompat.STATE_PLAYING ) {
playbackstateBuilder.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE |
PlaybackStateCompat.ACTION_PAUSE);
} else {
playbackstateBuilder.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE |
PlaybackStateCompat.ACTION_PLAY);
}
playbackstateBuilder.setState(state, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, 0);
gesMediaSession.setPlaybackState(playbackstateBuilder.build());
}
//-------------------------------Audio Focus and Calls Handling-------------------------------//
//Handle incoming phone calls
private boolean ongoingCall = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
#Override
public void onAudioFocusChange(int focusChange) {
switch( focusChange ) {
case AudioManager.AUDIOFOCUS_LOSS: {
// Lost focus for an unbounded amount of time:
// stop playback and release media player
if( gesMediaPlayer.isPlaying() ) {
gesMediaPlayer.stop();
}
/*gesMediaPlayer.release();
gesMediaPlayer = null;*/
break;
}
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: {
// Lost focus for a short time; Pause only and do not
// release the media player as playback is likely to resume
if (gesMediaPlayer.isPlaying()) {
gesMediaPlayer.pause();
}
break;
}
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
// Lost focus for a short time (ex. notification sound)
// but it's ok to keep playing at a temporarily attenuated level
if( gesMediaPlayer != null ) {
gesMediaPlayer.setVolume(0.2f, 0.2f);
}
break;
}
case AudioManager.AUDIOFOCUS_GAIN: {
//Invoked when the audio focus of the system is updated.
if( gesMediaPlayer != null ) {
if( !gesMediaPlayer.isPlaying() ) {
gesMediaPlayer.start();
}
gesMediaPlayer.setVolume(1.0f, 1.0f);
}
break;
}
}
}
private boolean requestAudioFocus() {
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
return result == AudioManager.AUDIOFOCUS_GAIN;
}
private boolean removeAudioFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
audioManager.abandonAudioFocus(this);
}
private void callStateListener() {
// Get the telephony manager
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
//Starting listening for PhoneState changes
phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
//if at least one call exists or the phone is ringing
//pause the MediaPlayer
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (gesMediaPlayer != null && gesMediaPlayer.isPlaying()) {
gesMediaPlayer.pause();
pausedPosition = gesMediaPlayer.getCurrentPosition();
ongoingCall = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
// Phone idle. Start/resume playing.
if (gesMediaPlayer != null) {
if (ongoingCall) {
ongoingCall = false;
gesMediaPlayer.seekTo(pausedPosition);
gesMediaPlayer.start();
}
}
break;
}
}
};
// Register the listener with the telephony manager
// Listen for changes to the device call state.
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
private BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if( gesMediaPlayer != null && gesMediaPlayer.isPlaying() ) {
gesMediaPlayer.pause();
}
}
};
//------------------------------------Less important methods----------------------------------//
#Nullable
#Override
public BrowserRoot onGetRoot(#NonNull String clientPackageName, int clientUid, #Nullable Bundle rootHints) {
if(TextUtils.equals(clientPackageName, getPackageName())) {
return new BrowserRoot(getString(R.string.app_name), null);
}
return null;
}
//Not important for general audio service, required for class
#Override
public void onLoadChildren(#NonNull String parentId, #NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
result.sendResult(null);
}
}
I apologize for the whole code but at this point I do not know what am I doing wrong anymore or where to look. Especially since the app did work in a previous version. Any suggestions are well appreciated if you guys see anything specific in my code. I try to catch exceptions where I can, but at the same time I am never sure where should I be putting the try-catch constructs. I'm trying to learn
Thank you to anyone!

How to run service for always in Android

In my application I want use service for get request to server.
I should run this service for always and not stop it!
I write below code in service, but just show for 5 time and when receive to 5 step. then not show Toast!
But I want always getData() and show Toast.
Service class :
public class NotifyService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
//Creating new thread for my service
//Always write your long running tasks in a separate thread, to avoid ANR
new Thread(new Runnable() {
#Override
public void run() {
//Your logic that service will perform will be placed here
//In this example we are just looping and waits for 5000 milliseconds in each loop.
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(5000);
} catch (Exception e) {
}
if (isRunning) {
ExploreSendData sendData = new ExploreSendData();
sendData.setPageIndex(1);
sendData.setPageSize(10);
sendData.setShowFollows(false);
sendData.setShowMovies(true);
sendData.setShowNews(true);
sendData.setShowReplies(false);
sendData.setShowSeries(true);
sendData.setShowSuggestions(false);
InterfaceApi api = ApiClient.getClient().create(InterfaceApi.class);
Call<ExploreResponse> call = api.getExplore(new SharedPrefrencesHandler(NotifyService.this)
.getFromShared(SharedPrefrencesKeys.TOKEN.name()), sendData);
call.enqueue(new Callback<ExploreResponse>() {
#Override
public void onResponse(Call<ExploreResponse> call, Response<ExploreResponse> response) {
if (response.body().getData() != null && response.body().getStatusCode() != 401
&& response.body().getStatusCode() != 402) {
Toast.makeText(NotifyService.this, "Test Show message ever 5second", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ExploreResponse> call, Throwable t) {
}
});
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
I copy this service code from internet, but just show 5times. I want show always.
How can I edit my codes and fix it? Please help me. Thanks
The problem is not in the service, services start and continue living as long as the app is alive and android doesn't kill it. For an infinite loop replace the "for loop" with "While loop". The below loop doesn't end.
while (true) {
......
......
......
}

Why Android devices won't read NFC tags after a long sleep?

I'm sorry for my bad English.
I develop an Android app using NFC. I added a method that stops unsecured keyguards temporarily to the app for the purpose of quickly uses NFC tags.
However, I thought stopping keyguards causes battery drains when sleeping, so I added a method that recovers keyguards when devices are sleeping.
As a result, I wrote codes shown below.
public class MainActivity extends Activity {
private NfcAdapter mAdapter;
private PowerManager mPowerManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// regist screen on / off actions receiver
IntentFilter scFilter = new IntentFilter();
scFilter.addAction(Intent.ACTION_SCREEN_ON);
scFilter.addAction(Intent.ACTION_SCREEN_OFF);
scFilter.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(mScreenReceiver, scFilter);
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String action = intent.getAction();
if (action != null && (action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)
|| action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)
|| action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))) {
// manage NFC Tags here
Log.d("MainActivity", "NFC Tags detected");
Toast.makeText(getApplicationContext(), "NFC Tags detected", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onResume() {
super.onResume();
// enableForegroundDispatch
if (mAdapter == null) {
mAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
}
if (mAdapter != null) {
Intent nfcIntent = new Intent(this, getClass());
nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, nfcIntent, 0);
mAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
} else {
Log.d("MainActivity", "failed getDefaultAdapter()");
}
}
#Override
public void onPause() {
if (mPowerManager != null) {
if (!mPowerManager.isScreenOn()) {
// clearWindowFlags only when device is sleeping
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
}
// disableForegroundDispatch
if (mAdapter != null) {
mAdapter.disableForegroundDispatch(this);
mAdapter = null;
}
super.onPause();
}
#Override
public void onDestroy() {
try {
// unregist screen on / off actions receiver
unregisterReceiver(mScreenReceiver);
} catch (IllegalArgumentException e) {
}
super.onDestroy();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return false;
}
private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == null) {
return;
}
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
} else if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
}
}
};
}
But, this code didn't perform as intended on my device.
I use Nexus 7 (1st, OS 4.3, Slide lock enabled).
First, when I launched the app and put my device into sleep, keyguards didn't recover with a probability of 30%. It sounds read sound effects with NFC tags even when sleeping.
Second, my device rarely won't read NFC tags after about an hour sleep with using the app. It will not even sound anything with NFC tags. But the condition goes off after sleep again or terminating the app.
Who does know causes of the bugs?

Background application not working

I have an Android application in When application go in background and headphone remove from phone alarm start.All is fine on foreground,but when application go in background its not work.I wrote code on activity onPause() as below
#Override
protected void onPause() {
try{
super.onPause();
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra("state")) {
int state = intent.getIntExtra("state", 0);
if (isHeadPhoneAttached && state == 0) {
isHeadPhoneAttached = false;
if (isTriggered) {
createNotification();
initTimerCounter();
makeToat();
/*handler.removeCallbacks(sendUpdatesToUI);*/
/*callTriggerActivity();*/
/*showDialog(Headphone_DIALOG);*/
}
} else if (!isHeadPhoneAttached && state == 1) {
isHeadPhoneAttached = true;
}
}
}
}, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
/*createNotification();
initTimerCounter() ;*/
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
but it's not working.Please anybody give me some idea.
You can't be sure if your application is running in the background so registering an BroadcastReceiver in the onPause method of an Activity is general bad practice.
You should use a Service instead

Keep Service running

Can anyone tell me the way to keep a Service always running or restarting itself when the user close it? I've watched that facebook services restart when i clear memory.
I don't want to make ForegroundServices.
You should create a sticky service. Read more about it here.
You can do this by returning START_STICKY in onStartCommand.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
Read also about application:persistent which is "Whether or not the application should remain running at all times". This is more troublesome - System will try not to kill your app which will effect others in the system, you should be careful using it.
I copied this from a service I used in an app I did before.
ITS IMPORTANT TO NOT UPDATE ANY UI. because you have no user interface in services. this applies to Toasts as well.
good luck
public class nasserservice extends Service {
private static long UPDATE_INTERVAL = 1*5*1000; //default
private static Timer timer = new Timer();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
_startService();
}
private void _startService()
{
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
doServiceWork();
}
}, 1000,UPDATE_INTERVAL);
Log.i(getClass().getSimpleName(), "FileScannerService Timer started....");
}
private void doServiceWork()
{
//do something wotever you want
//like reading file or getting data from network
try {
}
catch (Exception e) {
}
}
private void _shutdownService()
{
if (timer != null) timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped...");
}
#Override
public void onDestroy()
{
super.onDestroy();
_shutdownService();
// if (MAIN_ACTIVITY != null) Log.d(getClass().getSimpleName(), "FileScannerService stopped");
}
}

Categories

Resources