I want to send an SMS without user intervention so I crated a BroadcastReceiver to solve this problem. This BroadcastReceiver will receive "BOOT_COMPLETED" notification at bootup. In the OnReceive function we can send SMS (After 5 minutes of bootup). I tried this logic but it is not working.
I came to know from some other posts on this site that after Android 3.1+ we cannot use this kind of logic to meet this requirement. But I tried this logic on Android 2.3 and it seems that it is not working there either.
Please suggest to me how to solve this problem on Android 2.3 and Android 4.0+ versions. I don't want to create any UI for this requirement.
I am trying following piece of code.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.telephony.SmsManager;
import android.util.Log;
class MyCountDownTimer extends CountDownTimer {
private int no_of_attempts;
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
no_of_attempts = 0;
}
#Override
public void onFinish() {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage("+9198104084753", null, "Test Message ", null, null);
} catch (Exception e) {
Log.d("BGSMS","SMS Sending failed..Try to resend SMS");
no_of_attempts++;
if (no_of_attempts <= 3)
{
long startTime = 5 * 1000;
long interval = 1 * 1000;
CountDownTimer countDownTimer;
countDownTimer = new MyCountDownTimer(startTime, interval);
countDownTimer.start();
}
}
}
#Override
public void onTick(long millisUntilFinished) {
}
}
public class SalestrackerReceiver extends BroadcastReceiver {
private CountDownTimer countDownTimer;
private final long startTime = 5 * 1000;
private final long interval = 1 * 1000;
#Override
public void onReceive(Context context, Intent intent) {
Log.v("Anshul","Anshul Broadcast receiver received");
countDownTimer = new MyCountDownTimer(startTime, interval);
countDownTimer.start();
}
}
Manifest File :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sales_tracker"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="10" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name="SalestrackerReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
You have to create one service,which going to send sms after 5 min.
In Broadcastreceiver call your service.
public class MyReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
TimerTask hourlyTask = new TimerTask () {
#Override
public void run () {
Intent myIntent = new Intent(context,MyService.class);
startService(myIntent);
}
};
// schedule the task to run starting now and then every hour...
timer.schedule (hourlyTask,5000 * 60 * 1);
}
}
}
in myservice class you write code to send sms in Onstart() method.
You should start a service from your onReceive method in your (BOOT_COMPLETED) BroadcastReceiver.
See here:
http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html#startingservices_alarmmanager
Also note:
If you application is installed on the SD card, then it is not available after the android.intent.action.BOOT_COMPLETED event. Register yourself in this case for the android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE event.
Also note that as of Android 3.0 the user needs to have started the application at least once before your application can receive android.intent.action.BOOT_COMPLETED events.
Use pending Intent and Alarm Manager for send message after 5 minutes of boot up.
Intent i = new Intent(this,Shedulesms.class);
Bundle msg = new Bundle();
msg .putString("number", "1234567890");
msg .putString("message", "This is test message");
i.putExtras(msg );
PendingIntent pu=PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_ONE_SHOT);
AlarmManager am=(AlarmManager)getSystemService(ALARM_SERVICE);
Calendar cal= Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.MINUTE,cal.get(Calendar.MINUTE)+5);
am.set(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(),pu);
in Shedulesms.java
enter code here
SmsManager sms=SmsManager.getDefault();
Bundle b=getIntent().getExtras();
String number=b.getString("number");
String msg=b.getString("message");
sms.sendTextMessage(number, null,msg, null, null);
Give Permission in android manifiest file
<uses-permission android:name="android.permission.SEND_SMS" />
and register broadcast receiver in manifiest
As described in some answers in Trying to start a service on boot on Android, some phones have a fastboot-option. To support these phones, add
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
to your intent-filter.
Related
I'm attempting to make it so my app runs some code once per day at 6AM. This works just fine when the app is open and in the foreground, but if the app is closed by swiping it away, the code is never called at the appropriate time.
AlarmReceiver.java (For testing purposes, I have it just trying to display a Toast to verify it runs)
public class AlarmReceiver extends BroadcastReceiver {
public static final String intentAction = "com.mpagliaro98.action.NOTIFICATIONS";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(intentAction)) {
Toast.makeText(context, "RECEIVER CALLED", Toast.LENGTH_LONG).show();
}
}
}
MainActivity.java (Where the alarm is being set)
public class MainActivity extends AppCompatActivity {
...
private void setRecurringAlarm() {
// Set this to run at 6am
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getDefault());
updateTime.set(Calendar.HOUR_OF_DAY, 6);
updateTime.set(Calendar.MINUTE, 0);
updateTime.set(Calendar.SECOND, 0);
updateTime.set(Calendar.MILLISECOND, 0);
// Build the pending intent and set the alarm
Intent i = new Intent(AlarmReceiver.intentAction);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(),
0, i, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
assert am != null;
am.setRepeating(AlarmManager.RTC, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
}
}
AndroidManifest.xml (Just the relevant parts)
<uses-permission android:name="android.permission.SET_ALARM" />
<receiver
android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.mpagliaro98.action.NOTIFICATIONS" />
</intent-filter>
</receiver>
I've read through dozens of similar problems to this on this site and elsewhere and I'm seriously at a loss for why this won't work. Any help would be appreciated.
Try changing receiver to
<receiver android:process=":remote" android:name="AlarmReceiver"></receiver>
Should I use android: process =":remote" in my receiver?
I want to start ScheduledExecutorService exactly on 12 AM daily, but in my code schedule is not started. Can any one tell me Whether my code is Correct or not? If any other way available that would also helpful
public class MainActivity extends AppCompatActivity{
ScheduledExecutorService scheduler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scheduler = Executors.newScheduledThreadPool(1);
scheduleTask();
}
public void scheduleTask() {
final Runnable beeper = new Runnable() {
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(),"SCHEDULE STARTED",Toast.LENGTH_LONG).show();
}
}
}
}, 1500);
}
});
}
};
Calendar midnight = Calendar.getInstance();
midnight.set(Calendar.HOUR_OF_DAY, 0);
midnight.set(Calendar.MINUTE, 0);
midnight.set(Calendar.SECOND, 0);
midnight.set(Calendar.MILLISECOND, 1);
midnight.set(Calendar.DAY_OF_YEAR, midnight.get(Calendar.DAY_OF_YEAR) + 1);
long tillMidnight = midnight.getTimeInMillis() - System.currentTimeMillis() - 1;
long ticksTillMidnight = tillMidnight / 50;
final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper, ticksTillMidnight,20*60*60*24, TimeUnit.MILLISECONDS
);
scheduler.schedule(new Runnable() {
public void run() {
beeperHandle.cancel(true);
}
}, 6*6, TimeUnit.MILLISECONDS
);
}}
The answer is quite simple. In your case, a ScheduledExecutorService is bound to the lifetime of your process. If your process gets killed, then the ScheduledExecutorService will get killed along with it. Instead use an AlarmManager
Here are 3 steps
Create the Alarm
Create the BroadcastReceiver
Register the Receiver in the App Manifest
1. Create the Alarm
public void createAlarm() {
//System request code
int DATA_FETCHER_RC = 123;
//Create an alarm manager
AlarmManager mAlarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
//Create the time of day you would like it to go off. Use a calendar
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
//Create an intent that points to the receiver. The system will notify the app about the current time, and send a broadcast to the app
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, DATA_FETCHER_RC,intent, PendingIntent.FLAG_UPDATE_CURRENT);
//initialize the alarm by using inexactrepeating. This allows the system to scheduler your alarm at the most efficient time around your
//set time, it is usually a few seconds off your requested time.
// you can also use setExact however this is not recommended. Use this only if it must be done then.
//Also set the interval using the AlarmManager constants
mAlarmManager.setInexactRepeating(AlarmManager.RTC,calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntent);
}
2. Create the BroadcastReceiver
//This is the broadcast receiver you create where you place your logic once the alarm is run. Once the system realizes your alarm should be run, it will communicate to your app via the BroadcastReceiver. You must implement onReceive.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Your code once the alarm is set off goes here
//You can use an intent filter to filter the specified intent
}
}
3. In your app manifest register the receiver
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package">
//This is a useful permission as it allows your apps alarm to still be active once a reboot takes place
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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>
<receiver
android:name=".MainActivity$AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
I have a boot receiver set up in my manifest which launches a WakefulBroadcastReceiver which then starts a ServiceIntent to create alarms.
My manifest has this:
<receiver android:name=".controllers.receivers.AlarmBootReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
As well as the RECEIVE_BOOT_COMPLETED permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
My AlarmBootReceiver is this:
public class AlarmBootReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent alarmBootServiceIntent = new Intent(context, AlarmBootService.class);
startWakefulService(context, alarmBootServiceIntent);
}
}
and my IntentService is this:
public class AlarmBootService extends IntentService {
public AlarmBootService() {
super("AlarmBootService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.wtf("Boot", "Boot receiver started");
//Get list of classes from realm and set up alarms for each
Realm.init(getBaseContext());
Realm realm = Realm.getDefaultInstance();
RealmResults<Class> classes = realm.where(Class.class).findAll();
//For each day in days string, create an alarm an hour before fromtime
MainActivity ma = new MainActivity();
for (Class c : classes) {
for (char day : c.getDays().toCharArray()) {
//Convert SMTWRFA char to calendar day int
int d = ClassDialog.charToDay(day);
//Create the alarm
ma.createWeeklyAlarmForDay(d, c.getName(),
c.getBuilding(),
c.getFromAMPM().equals("AM") ? Calendar.AM : Calendar.PM,
c.getTimeFromH(), c.getTimeFromM());
}
}
//Release wakelock
AlarmBootReceiver.completeWakefulIntent(intent);
}
}
But the service never appears to be launched. I never see my "Boot receiver started" log in the output, and alarms aren't registered. Have I done something wrong?
I have done an app as tutorial to learn how to restart deleted alarms after phone is rebooted. After reboot BroadcastReceiver receives BOOT_COMPLETED action and launches a service, which restarts all alarms. Alarms create notification when they are called. After first tests I have received notifications at expected time and then forgot about this tutorial app and didn't turn the phone off.
However, I'm still getting notifications on my screen as if the app has restarted alarms again. During the day I have received twice and all of them are unclear why. The only thing that may launch the restarting alarms is BOOT_COMPLETED action. What's going wrong here?
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.marat.recyclerviewtutorial">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
// list of activities
<service android:name=".BootService"/>
<receiver android:name=".AlarmBroadcastReceiver"/>
<receiver android:name=".RestartAlarmsReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
RestartAlarmsReceiver.java
public class RestartAlarmsReceiver extends BroadcastReceiver {
private static final String TAG = "myTag";
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent i = new Intent(context, BootService.class);
ComponentName service = context.startService(i);
if (null == service) {
// something really wrong here
Log.e(TAG, "Could not start service ");
}
else {
Log.e(TAG, "Successfully started service ");
}
} else {
Log.e(TAG, "Received unexpected intent " + intent.toString());
}
}
}
BootService.java
public class BootService extends Service {
private static final String TAG = "myTag";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
Database db = new Database(this);
db.open();
ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>>();
data = db.getData();
db.close();
Log.d(TAG, "db is openned");
for (int i=0; i<data.size(); i++) {
Intent notif = new Intent(this, AlarmBroadcastReceiver.class);
notif.putExtra("Text", data.get(i).get(2));
notif.putExtra("Position", data.get(i).get(0));
int sec = Integer.parseInt(data.get(i).get(3));
Log.d(TAG, "intent is openned");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, Integer.parseInt(data.get(i).get(0)), notif, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (sec * 1000), pendingIntent);
Log.d(TAG, "Alarm is restarted");
}
Log.d(TAG, "before returning service");
return Service.START_STICKY;
}
}
It's already huge portion of code. But if you will need other parts of my app I will include them.
Thanks in advance!
I think this is because of START_STICKY. I think during the day the system closes your running Service to free resources, and START_STICKY forces it to restart. And on restart onStartCommand() is triggered again.
The decision may to use IntentService instead. I don't see the need of using Service here.
I have:
MyApp extends Application with onCreate:
sendBroadcast(refreshAlarm);
Log.d(TAG, "broadcast sent with intent " + refreshAlarm);
Log.d(TAG, "onCreate");
where
static final Intent refreshAlarm = new Intent(ACTION_REFRESH_RECEIVER);
public static final String ACTION_REFRESH_RECEIVER = "com.example.myapp.REFRESH_RECEIVER";
BroadcastReceiver :
package com.example.myapp;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.preference.PreferenceManager;
import android.util.Log;
public class RefreshReceiver extends BroadcastReceiver
{
private static final String TAG = "RefreshReceiver";
#Override
public void onReceive(Context context, Intent intent)
{
Log.d(TAG, "broadcast received with intent " + intent);
long interval = Long
.parseLong(PreferenceManager.getDefaultSharedPreferences(
context).getString("delay", "900")) * 1000;
PendingIntent operation = PendingIntent.getService(context, -1,
new Intent(context, RefreshService.class),
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(operation);
if (interval > 0)
{
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), interval, operation);
}
Log.d(TAG, "onReceive: delay = " + interval);
}
}
declared in manifes:
<receiver android:name="com.example.myapp.RefreshReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="com.example.myapp.REFRESH_RECEIVER" />
</intent-filter>
</receiver>
It seems to me that I have all I need to make this work. Broadcast is send in onCreate (I can see in log it is indeed send). Broadcast is declared with intent filter to receive refreshAlarm intent, but it doesn't receive it and I cannot figure out why. Do I need anything else?
if you put BroadCastReceiver in mainfest.xml you don't need to regiter it in code , register it in code only if you create it in your Code
this is example here :
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="android.mybroadcast" />
</intent-filter>
</receiver>
and here to call it from your class file ,
Intent intent = new Intent();
intent.setAction("android.mybroadcast");
sendBroadcast(intent);
try to register your broadcast receiver by programmatically
public void registerBroadcastReceiver(View view) {
this.registerReceiver(broadCastReceiver, new IntentFilter(
"com.example.myapp.REFRESH_RECEIVER"));
Toast.makeText(this, "Enabled broadcast receiver", Toast.LENGTH_SHORT)
.show();
}
and unregister by this
public void unregisterBroadcastReceiver(View view) {
this.unregisterReceiver(broadCastReceiver);
Toast.makeText(this, "Disabled broadcst receiver", Toast.LENGTH_SHORT)
.show();
}
It could be possible that its not working because your Receiver and the package name you are using for registering in your manifest do not match.
Make sure that your package name matches your respective package for your receiver.
You said
MyApp extends Application
you should register MyApp as application in android manifest.
put this line in android manifest application element
android:name="your.package.MyApp"
Where your.pacakage is the package where MyApp file is located. Now your application element should look as follows
<application
android:name="your.package.MyApp"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/yourTheme" >
I had the same problem. It seems that the registered broadcastreceivers only work for system actions. With my custom action it only worked as long as my app was running (activity was in activity stack).
My workaround is to create an activity for it. This does not work in background, however it gives you the possibility to catch events from other apps
<activity android:name=".ImportToProActivity">
<intent-filter>
<action android:name="com.sourcecastle.logbook.ImportToProActivity"/>
</intent-filter>
</activity>
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.sourcecastle.freelogbook", "com.sourcecastle.logbook.ImportToProActivity"));
startActivity(intent);