Ive implemented a mediaplayer and mediacontroller that streams a mp3 url. However my device on the TMobile network doesnt get a great 3G signal so it operates on EDGE. Im assuming that the mediaplayer is crashing because the stream is too slow or incomplete, is there a timeout I can set?
There is no timeout method in MediaPlayer, but you can implement it yourself - there are variety of ways you can do that.
I suggest one of them, that I used myself and it worked for me - BroadcastReceiver
Code would look like that:
public class ConnectivityCheckingReceiver extends WakefulBroadcastReceiver
{
private AlarmManager alarmManager;
private PendingIntent pendingIntent;
#Override
public void onReceive(Context context, Intent intent)
{
if (MusicService.mediaPlayer != null)
{
if (!MusicService.mediaPlayer.isPlaying())
Log.v("Music", "Music is NOT playing");
//stop service and notify user
else
Log.v("Music", "Music is playing");
}
else
{
Log.v("Music", "User stopped player");
}
}
public void setAlarm (Context context, int hour, int minute, int second)
{
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, ConnectivityCheckingReceiver.class);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
In your activity/service/fragment you add this line:
ConnectivityCheckingReceiver conCheck = new ConnectivityCheckingReceiver();
conCheck.setAlarm(context, hour, min, second);
You will need to implement hour/min/second checking logic yourself, but it's easily done with libraries like Joda Time.
And don't forget to add to your manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver android:name=".receivers.ConnectivityCheckingReceiver" />
Ps, my solution is not perfect, but I have not seen any good answers for this question, so if find one, please share it.
You can also use prepare() instead of prepareAsync() on MediaPlayer and put it inside asyncTask or worker thread; then you can inmplement timeout functionality by yourself. I will add a code sample later, but the idea is clear I think.
Indeed Mediaplayer takes some time to buffer and on slow networks that can lead to problems.
You cannot control this process, there is no user set timeout, but you can make sure it doesn't crash your app by catching all exception that methods such as setDataSource(), prepare(), prepareAsync(), and start() can throw.
Related
I am developing an app built on this example: https://github.com/xamarin/mobile-samples/tree/master/BackgroundLocationDemo
The example works and the location updates are coming in as expected. However, Android keeps showing an notification that the service is running and draining battery. Now, all my users have a defined working schedule (list of Start to End DateTime per day e.g 8am-1pm, 4pm-8pm), and I want that the service is only running between those working times. This means that I need to start/stop the service whenever the schedule says the user is working or not.
I've asked this question before but wondering if anyone figured out an efficient and solid way to achieve this type of service that is operating from a time schedule?
You can use AlarmManager to execute a task in specific time.
For example, I want my task running at the 10:51 am every day, I can use following code to execute it.
public static void startAlarmBroadcastReceiver(Context context)
{
Intent _intent = new Intent(context, typeof( AlarmBroadcastReceiver));
PendingIntent pendingIntent = PendingIntent.GetBroadcast(context, 0, _intent, 0);
AlarmManager alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService);
// Remove any previous pending intent.
alarmManager.Cancel(pendingIntent);
Calendar cal = Calendar.Instance;
cal.Set( CalendarField.HourOfDay, 10);
cal.Set(CalendarField.Minute, 51);
cal.Set(CalendarField.Second, 0);
alarmManager.SetRepeating(AlarmType.RtcWakeup, cal.TimeInMillis, AlarmManager.IntervalDay, pendingIntent);
}
Here is code about AlarmBroadcastReceiver.
[BroadcastReceiver(Enabled = true, Exported = false)]
public class AlarmBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Toast.MakeText(context, "Received intent!", ToastLength.Short).Show();
}
}
Do not forget to add following permissions.
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Here is running gif.
I wrote an application which is able to set alarms based on some specif times. These specific times change day by day. For example, sunrise time changes every day. So, I defined a main activity which is responsible to call setExact() method every night at 11:55 p.m and then it has to set tomorrow's alarms based on the specific times for tomorrow. The issue is, it does not work! When I set the alarm, it just works for one time, and it is not going to be set for the second time. I really need help. Thank you :)
public class MainPage extends AppCompatActivity {
private Calendar calendar = new GregorianCalendar();
protected GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setMainAlarm();
}
private void setMainAlarm() {
AlarmManager alarmMgr = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(".mainAlarmReciever");
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar alertCalendar = Calendar.getInstance();
alertCalendar.set(Calendar.HOUR,23);
alertCalendar.set(Calendar.MINUTE,54);
alertCalendar.set(Calendar.SECOND,59);
if (Build.VERSION.SDK_INT >= 23) {
alarmMgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alertCalendar.getTimeInMillis(), alarmIntent);
}else{
alarmMgr.setExact(AlarmManager.RTC_WAKEUP, alertCalendar.getTimeInMillis(), alarmIntent);
}
}
This is the related receiver class for that:
public class mainAlarmReciever extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
AlarmSetter.createOrUpdateAllAlarms(context);
this.completeWakefulIntent(intent);
}
The issue is you do not set the mainAlarm for tomorrow on your mainAlarmReciever.
Imagine that your mainAlarmReciever->onRecieve run at 11:54:59 P.M tonight. And it does whatever tasks you want to do. You should also set the mainAlarm for Tomorrow at 11:54:59 P.M in your onRecieve function.
Another option is using setRepeating (as CommonsWare mentioned it is not exact after API 19+).
I am attempting to use CommonsWare's WakefulIntentService in a new application, specifically its ability to easily schedule the intent service to run at a later time.
I have a PreferenceActivity that allows the user to pick the schedule that the service is run (daily at 5am for example). Once the user makes a change to the preference value, I call:
AutoDownloadIntentServiceAlarmListener alarmListener = new AutoDownloadIntentServiceAlarmListener();
alarmListener.setForcedHour(5); // we want to schedule alarm for 5am everyday.
WakefulIntentService.scheduleAlarms(alarmListener, this, true);
For some reason, the desired IntentService (that extends WakefulIntentService) immediately starts up and performs its work.
Here is the implementation of of AutoDownloadIntentServiceAlarmListener:
public class AutoDownloadIntentServiceAlarmListener implements WakefulIntentService.AlarmListener {
private static final String TAG = "AutoDownloadIntentServiceAlarmListener";
private int mForcedHour = -1;
#Override
public long getMaxAge() {
return AlarmManager.INTERVAL_DAY * 2;
}
public void setForcedHour(int forcedHour) {
mForcedHour = forcedHour;
}
#Override
public void scheduleAlarms(AlarmManager alarmManager, PendingIntent pendingIntent, Context context) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
String autoDownloadTimePref = MyApplication.getInstance().getPrefs().getString("autoDownloadEpisodesSchedule", "0");
int hourOfAlarm = Integer.parseInt(autoDownloadTimePref);
// if this class has been created with a specific hour
// use it instead of the value obtained from SharedPreferences above.
if (mForcedHour > -1) {
Log.w(TAG, "Forced hour has been set for this AlarmListener. " + mForcedHour);
hourOfAlarm = mForcedHour;
}
calendar.set(Calendar.HOUR_OF_DAY, hourOfAlarm);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Log.d(TAG, String.format("Scheduled inexact alarm for %d", hourOfAlarm));
}
#Override
public void sendWakefulWork(Context context) {
Intent serviceIntent = new Intent(context, AutoDownloadIntentService.class);
WakefulIntentService.sendWakefulWork(context, serviceIntent);
}
}
It is my intention that the service does not startup as soon as it is scheduled, and instead starts up only at 5am the next day. (and continues to repeat on this schedule indefinitely, or until the user elects to disable or change its schedule)
What am I doing wrong?
It is my intention that the service does not startup as soon as it is scheduled, and instead starts up only at 5am the next day.
Except that's not what your code does, ~80% of the time. Your code says that it should run at 5am today, as you are getting the current time and not changing the day. Most of the time, 5am today is in the past, and so AlarmManager will immediately do its work.
You need to see if your calculated Calendar is older than now, and if so, add a day.
public void runSound(){
Intent it = new Intent(Values.TAG_EXECUTE_ALARM);
PendingIntent pendIntent = PendingIntent.getBroadcast(this, 0, it, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND,0);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
long time = calendar.getTimeInMillis();
alarm.set(AlarmManager.RTC_WAKEUP,time,pendIntent);
}
This method is called from a service. My service is supposed to play a sound to notify the user even if the device is on sleep mode.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
MediaPlayer player = MediaPlayer.create(arg0, R.raw.order_alarm);
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.start();
}
This is the class that will actually play the sound. Unfortunately the devices doesn't wake up and the sound is not played. When runSound is called before the device enters in sleep mode the sound works perfecly... Any ideas?
Edit:
-> Removed static references (yes, they were dumb, since runSound is inside a service).
-> Yes, the tag value is defined in receiver intent-filter
-> Improved the question.
Well, I cant test now, but looking at your code I can see some problems.
At getBroadcast(), the last parameter has to be a flag, like "FLAG_CANCEL_CURRENT", and I am not sure if 0 is a valid flag.
And at "long time = calendar.getTimeInMillis();" it looks like you are putting a time in the past, well if it is in the past, it will not run, try add 5000 (5s).
All others things looks fine to me.
I am new to Android. I am trying to develop an Alarm Application, which is actually a speaking clock. I just want the clock to use TextToSpeech API and speak out the greeting stuff and the current time as soon as the alarm time is ticked. The speech part is done. And now I want to implement the Alarm functionality. But Initially I am just trying to display a toast after 10 secs in order to check whether my classes are working properly. And I am not getting the desired response and I don't know why ? Following are the classes
Main Class aClockActivity
public class aClockActivity extends Activity {
/** Called when the activity is first created. */
private PendingIntent mAlarmSender;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button1 = (Button)findViewById(R.id.buttonOn);
button1.setOnClickListener(mStartAlarmListener);
Button button2 = (Button)findViewById(R.id.buttonOff);
button2.setOnClickListener(mStopAlarmListener);
}
private OnClickListener mStartAlarmListener = new OnClickListener() {
public void onClick(View v) {
// We want the alarm to go off 30 seconds from now.
//long firstTime = SystemClock.elapsedRealtime();
EditText Ehour = (EditText) findViewById(R.id.hour);
EditText Eminute = (EditText) findViewById(R.id.minute);
CharSequence CharHour = Ehour.getText();
CharSequence CharMinute = Eminute.getText();
int hour = Integer.parseInt(CharHour.toString());
int minute = Integer.parseInt(CharMinute.toString());
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
// calendar.add(Calendar.MINUTE, 1);
cal.add(Calendar.SECOND, 10);
mAlarmSender = PendingIntent.getBroadcast(aClockActivity.this,
0, new Intent(aClockActivity.this, Alarm_Broadcast.class), 0);
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), mAlarmSender);
// Tell the user about what we did.
Toast.makeText(aClockActivity.this, "The Alarm is Set",
Toast.LENGTH_LONG).show();
}
};
private OnClickListener mStopAlarmListener = new OnClickListener() {
public void onClick(View v) {
// And cancel the alarm.
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.cancel(mAlarmSender);
// Tell the user about what we did.
Toast.makeText(aClockActivity.this, "Setting off the alarm",
Toast.LENGTH_LONG).show();
}
};
Second Class Alarm_Broadcast
public class Alarm_Broadcast extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm worked", Toast.LENGTH_LONG).show();
}
}
Note: Just ignore the Edittext part in the OnClick() method, I'd use it later on.
Apart from the above problem there are few questions that I would like to ask.
1) How can I implement this app so that when the alarm is set, it can actually run as a service in the notification bar where the original AlarmClock runs. So that even if the app is closed its still running to invoke the alarm message at the right time.
2) I cannot show any Dialog box or can use TTS if the AlarmManager invokes a Class that extends either Service or BroadcastReciever.
3) I would appreciate if some one give me the idea to implement this app, I am sure there are many experts who would have gone through the same application.
Regards
Omayr
Here is some sample code i used in an alarm clock app hope it helps.
To set the alarm:
private void setAlarm(){
Context context = getApplicationContext();
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OnAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
myCal = Calendar.getInstance();
myCal.setTimeInMillis(TIME_THE_ALARM_SHOULD_GO_OFF_AS_A_LONG);
mgr.set(AlarmManager.RTC_WAKEUP, myCal.getTimeInMillis(), pi);
Log.i(myTag, "alarm set for " + myCal.getTime().toLocaleString());
Toast.makeText(getApplicationContext(),"Alarm set for " + myCal.getTime().toLocaleString(), Toast.LENGTH_LONG).show();
}
This goes in the onAlarmReceiver class:
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AlarmActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
this will start AlarmActivity whenever it needs to go off. In your case you'd put the toast and speech into the AlarmActivity.
How can I implement this app so that when the alarm is set, it can actually run as a service in the notification bar where the original AlarmClock runs. So that even if the app is closed its still running to invoke the alarm message at the right time.
Do not do this. Having a service stick around in memory 24x7 to watch a clock is a waste of RAM and will get you attacked by task killers, reducing your app's effectiveness. Please stick with AlarmManager.
I cannot show any Dialog box or can use TTS if the AlarmManager invokes a Class that extends either Service or BroadcastReciever.
Start an activity, perhaps a dialog-themed activity.
Just got the answer, whatever service, receiver, activity and etc you are using, you need to register it in your AndroidManifest.xml. Or else it wont work