Edit: I have figured out that when you set the alarm for a time before the current time it imediately goes off
I am creating an alarm app that has an activity that you use to create the alarm, and then it registers it with the android system. The problem I am having is that as soon as you create the alarm it goes off. I have also seen some odd behaviour with further testing, if you change the time in the time picker before you change the name it goes off at the correct time if not it just goes off as soon as it is created. Here is my alarm class which is used to create the pending-intent for the alarm(at least the important parts):
public class Alarm {
private String name;
private int id;
private Calendar time;
private boolean on = true;
public Alarm(String name, int id, Calendar time) {
this.setName(name);
this.setId(id);
this.setTime(time);
}
public Alarm() {
}
...
public PendingIntent createPendingIntent(Context context) {
Intent intent = new Intent(context, MathAlarmReceiverActivity.class);
intent.putExtra("name", getName());
PendingIntent pendingIntent = PendingIntent.getActivity(context,
id, intent, PendingIntent.FLAG_CANCEL_CURRENT);
return pendingIntent;
}
...
}
I thought that the problem might be where I created the intent, but when I changed the time in the time picker before I changed the name, it went off at the correct time so I was able to rule that out.
Next I have my Activity that actually has the time-picker:
public class EditActivity extends Activity {
public static int CODE_EDIT = 100;
public static int CODE_ADD = 101;
Button doneButton;
TimePicker tp;
EditText editName;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit);
doneButton = (Button) findViewById(R.id.buttonDone);
doneButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
done();
}
});
tp = (TimePicker) findViewById(R.id.timePicker);
editName = (EditText) findViewById(R.id.editTextAlarmName);
if (getIntent().getExtras().getInt("requestCode") == CODE_ADD) {
setTitle("Add Alarm");
doneButton.setText("Add Alarm");
} else {
doneButton.setText("Edit Alarm");
editName.setText(getIntent().getExtras().getString("name"));
Calendar c = TimeUtils.stringToCalendar(getIntent().getExtras().getString("time"));
tp.setCurrentHour(c.get(Calendar.HOUR_OF_DAY));
tp.setCurrentMinute(c.get(Calendar.MINUTE));
setTitle("Edit Alarm");
}
if (android.os.Build.VERSION.SDK_INT > 10) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
...
private void done() {
String name = editName.getText().toString().trim();
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, tp.getCurrentHour());
c.set(Calendar.MINUTE, tp.getCurrentMinute());
String time = TimeUtils.calendarToString(c);
if (name.length() == 0) {
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setMessage("Please enter an alarm name!");
b.setNeutralButton("Ok", null);
b.show();
} else {
Intent returnIntent = new Intent();
returnIntent.putExtra("name", name);
returnIntent.putExtra("time", time);
if (getIntent().getExtras().getInt("requestCode") == CODE_EDIT) {
returnIntent.putExtra("id", getIntent().getExtras()
.getInt("id"));
returnIntent.putExtra("on",
getIntent().getExtras().getBoolean("on"));
}
setResult(RESULT_OK, returnIntent);
finish();
}
}
...
}
Then I thought well maybe when I didn't do it that specific way it somehow changed what was in the time-picker, but I wasn't sure how that could happen! Here I have my method for adding the alarm to the android system:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == EditActivity.CODE_EDIT) {
dataSource.update_byID(
data.getExtras().getInt("id"),
TimeUtils.stringToCalendar(data.getExtras().getString(
"time")), data.getExtras().getString("name"),
data.getExtras().getBoolean("on"));
AlarmManager am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
for(int i = 0; i < dataSource.getAllAlarms().size(); i++) {
if(dataSource.getAllAlarms().get(i).getId() == data.getExtras().getInt("id")) {
Alarm tempAlarm = dataSource.getAllAlarms().get(i);
am.setRepeating(AlarmManager.RTC_WAKEUP, tempAlarm.getTime()
.getTimeInMillis(), AlarmManager.INTERVAL_DAY, tempAlarm
.createPendingIntent(this));
break;
}
}
}
if (requestCode == EditActivity.CODE_ADD) {
Alarm tempAlarm = dataSource.createAlarm(
data.getExtras().getString("name"),
TimeUtils.stringToCalendar(data.getExtras().getString(
"time")));
AlarmManager am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, tempAlarm.getTime()
.getTimeInMillis(), AlarmManager.INTERVAL_DAY, tempAlarm
.createPendingIntent(this));
}
}
refreshList();
}
And also these are the methods I used to convert a Calendar to string and back, I thought maybe I made an error here, but I tested the methods and they work:
public static String calendarToString(Calendar c) {
return String.valueOf(c.get(Calendar.HOUR)) + ":"
+ getMinuteInReadableFormat(c.get(Calendar.MINUTE))
+ (((c.get(Calendar.AM_PM)) == Calendar.AM) ? "AM" : "PM");
}
public static Calendar stringToCalendar(String s) {
String[] t = s.split(":");
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR, Integer.valueOf(t[0]));
c.set(Calendar.MINUTE, minuteToInt(t[1]));
c.set(Calendar.AM_PM, (t[1].endsWith("AM") ? Calendar.AM : Calendar.PM));
return c;
}
public static String convert12(String s) {
String newString = null;
if (s.startsWith("0")) {
newString = s.replaceFirst("0", "12");
}
if (newString == null) {
return s;
} else {
return newString;
}
}
private static String getMinuteInReadableFormat(int m) {
if (m < 10) {
return "0" + String.valueOf(m);
} else {
return String.valueOf(m);
}
}
private static int minuteToInt(String m) {
String x = m;
if (m.startsWith("0")) {
x = m.replaceFirst("0", "");
}
String y = x.replace("AM", "");
String z = y.replace("PM", "");
return Integer.valueOf(z.trim());
}
My problem is that as soon as you create the alarm it goes off. I have also seen some odd behaviour with further testing, if you change the time in the time picker before you change the name it goes off at the correct time if not it just goes off as soon as it is created. And I am not sure what to do know because I don't know what the problem is.
Also Thank You for taking the time to read my question.
Well I've solved the problem. For anyone that has a similar problem here is the solution. When I was creating an alarm for a time earlier than the current time it would go off immediately. The solution is to add the equivalent of 24 hours to the time you want when setting the alarm.
Related
I'd like to know if there's some way to set a timeout for an Intent started via startActivityForResult, so when the time is passed some actions can be performed with the activity of the mentioned intent (in my case finishing it).
There doesn't seem to be any direct way to set a timeout directly to the Intent, but this doesn't look too much to worry about, as I guess I could create a CountDownTimer that in onFinish() would call the code to finish the intent.
Problem is I don't see a way to finish that ActivityForResult.
Is there any way to do this?
Well, I finally got to solve the problem, indeed it wasn't very difficult.
For my particular case of INTENT_PICK the following code is valid to stop the activity after 2 minutes:
final int RQS_PICKCONTACT = 1;
[...]
Intent intentPickContact = new Intent(Intent.ACTION_PICK, uriContact);
startActivityForResult(intentPickContact, RQS_PICKCONTACT);
mcd = new CountDownTimer(120000, 10000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
try
{
finishActivity(RQS_PICKCONTACT);
}
catch (Exception ex)
{
}
}
}.start();
In my case I wanted to limit the time a user was doing a task so I created my own timer class.
public class Timer {
private static final String TAG = "Timer" ;
int timeout;
Context mContext;
boolean compleatedTask;
String timeoutKey;
CountDownTimer countDown;
public Timer(Context mContext, int timeout, String timeoutKey){
this.timeout = timeout;
this.mContext = mContext;
this.timeoutKey = timeoutKey;
}
public void startTimer() {
this.countDown = new CountDownTimer(this.timeout, 1000) {
public void onTick(long millisUntilFinished) {
Log.i(TAG, "OnTick, context: " + mContext + ", milisUntilFinished: " + millisUntilFinished + ", compleatedTask: " + compleatedTask);
if(compleatedTask)
cancel();
}
public void onFinish() {
Log.i(TAG, "OnFinish, context: " + mContext + ", compleatedTask: " + compleatedTask);
try
{
if(!compleatedTask){
Intent intent = new Intent(mContext, UnsuccessfullPosTaskActivity.class);
intent.putExtra("error", StateMachine.databaseAccess.getDictionaryTranslation(timeoutKey, StateMachine.language));
mContext.startActivity(intent);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
};
countDown.start();
}
public void setCompleatedTask(boolean compleatedTask){
this.compleatedTask = compleatedTask;
if(compleatedTask)
countDown.onFinish();
}
}
Then in your activity
int timeout = 1000;
Timer timer = new Timer(Activity.this, timeout);
timer.startTimer();
//do stuff
if(conditionToStop)
timer.setCompleatedTask(true);
And if you are using recycle views and you want to stop the counter when they click an option just send the timer object to your custom recycle view adapter.
I am trying to run an accounting calculator in the background using JobScheduler, but somehow, it won't do the calculation. The program runs smoothly, thats why it confuses me why it doesn't work. I appreciate your help.
Here's my Job Service class:
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyJobService extends JobService {
private JobParameters params;
int num1a;
int num1b;
int num2a;
int num2b;
int num3a;
int num3b;
int num4a;
int num4b;
int num5a;
int num5b;
int sum1;
int sum2;
int sum3;
int sum4;
int sum5;
SharedPreferences preferences;
SharedPreferences.Editor editor;
#Override
public boolean onStartJob(JobParameters params) {
this.params = params;
Toast.makeText(getApplicationContext(), "Start", Toast.LENGTH_LONG).show();
new MonthlyTask().execute();
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
return false;
}
private class MonthlyTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPostExecute(Void xVoid) {
super.onPostExecute(xVoid);
jobFinished(params, false);
Toast.makeText(getApplicationContext(), "Finish", Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(Void... params) {
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
editor = preferences.edit();
try {
num1a = preferences.getInt("expense1", 0);
num1b = preferences.getInt("subtotal1", 0);
num2a = preferences.getInt("expense2", 0);
num2b = preferences.getInt("subtotal2", 0);
num3a = preferences.getInt("expense3", 0);
num3b = preferences.getInt("subtotal3", 0);
num4a = preferences.getInt("expense4", 0);
num4b = preferences.getInt("subtotal4", 0);
num5a = preferences.getInt("expense5", 0);
num5b = preferences.getInt("subtotal5", 0);
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
sum1 = num1a + num1b;
sum2 = num2a + num2b;
sum3 = num3a + num3b;
sum4 = num4a + num4b;
sum5 = num5a + num5b;
editor.putInt("subtotal1", sum1);
editor.putInt("subtotal2", sum2);
editor.putInt("subtotal3", sum3);
editor.putInt("subtotal4", sum4);
editor.putInt("subtotal5", sum5);
return null;
}
}
}
Here's my Main Activity
public class MainActivity extends AppCompatActivity implements android.view.View.OnClickListener{
//Do stuffs
public void onClick(View view) {
if (view == findViewById(R.id.btnSave)) {
JobInfo.Builder builder = new JobInfo.Builder(1, new ComponentName(getPackageName(),
MyJobService.class.getName()));
//run job service after every 5 seconds, which put back to 15 mins...but thats fine
builder.setPeriodic(5000);
builder.setPersisted(true);
jobScheduler.schedule(builder.build());
finish();
}}
I am trying to run an accounting calculator in the background using JobScheduler
This example is really strange.
but somehow, it won't do the calculation
Um, well, if by "the calculation", you mean addition, it is doing the addition. However, you then throw away the results. You edit() the SharedPreferences without calling apply() or commit() to save the changes.
I found some problem for TimePicker widget. After user change time in widget setHour and setMinute methods not works.
public class MainActivity extends AppCompatActivity {
private Button mButton;
private TimePicker mTimePicker;
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.reset);
mTimePicker = (TimePicker) findViewById(R.id.timePicker);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
mTimePicker.setHour(hour);
mTimePicker.setMinute(minute);
Log.v(TAG, "onClick: " + hour + "=>" + mTimePicker.getHour());
Log.v(TAG, "onClick: " + minute + "=>" + mTimePicker.getMinute());
}
});
}
}
Step for reproduce:
Run app (my time: 13:21)
Change time on the Widget (21:21)
Tap on the Reset button
Result:time not reset to 13:21
Log:
03-30 13:18:05.765 30923-30923/ru.neverdark.timepickerproblem
V/MainActivity: onClick: 13=>21 03-30 13:18:05.765
30923-30923/ru.neverdark.timepickerproblem V/MainActivity: onClick:
18=>18
Any workaround for this problem?
Same bug I found in Issue Tracker: https://code.google.com/p/android/issues/detail?id=208180 but in SDK25 not fixed...
Demo project on the github: https://github.com/yankovskiy/TimePickerProblem
Well, I have to admit, this is not my proudest code.
But as a workaround you can have this:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar cal = Calendar.getInstance();
int currentHour = cal.get(Calendar.HOUR_OF_DAY);
int currentMinute = cal.get(Calendar.MINUTE);
fixValues();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mTimePicker.setHour(currentHour);
mTimePicker.setMinute(currentMinute);
} else {
mTimePicker.setCurrentHour(currentHour);
mTimePicker.setCurrentMinute(currentMinute);
}
}
});
private void fixValues() {
// bug is not reproducible in APIs 24 and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) return;
try {
int hour, minute;
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
hour = mTimePicker.getHour();
minute = mTimePicker.getMinute();
} else {
hour = mTimePicker.getCurrentHour();
minute = mTimePicker.getCurrentMinute();
}
Field mDelegateField = mTimePicker.getClass().getDeclaredField("mDelegate");
mDelegateField.setAccessible(true);
Class<?> clazz;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
clazz = Class.forName("android.widget.TimePickerClockDelegate");
} else {
clazz = Class.forName("android.widget.TimePickerSpinnerDelegate");
}
Field mInitialHourOfDayField = clazz.getDeclaredField("mInitialHourOfDay");
Field mInitialMinuteField = clazz.getDeclaredField("mInitialMinute");
mInitialHourOfDayField.setAccessible(true);
mInitialMinuteField.setAccessible(true);
mInitialHourOfDayField.setInt(mDelegateField.get(mTimePicker), hour);
mInitialMinuteField.setInt(mDelegateField.get(mTimePicker), minute);
} catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
}
Tested on APIs 21, 22 and 23.
Bug is not reproducible in APIs 24, 25.
protected Dialog onCreateDialog(int id) {
checkMark = (Button) findViewById(R.id.button13) ;
checkMark.setVisibility(View.VISIBLE) ;
switch (id) {
case TIME_DIALOG_ID:
// set time picker as current time
return new TimePickerDialog(this,
timePickerListener, hour, minute,false);
case TIME_DIALOG_ID_ON:
// set time picker as current time
return new TimePickerDialog(this,
timePickerListenerOn, hour, minute,false);
}
return null;
}
How about this?
picker.setCurrentHour(date.getHours())
picker.setCurrentMinute(date.getMinutes())
Problem:
I have an existing app that I would like to implement Android 6.0's Runtime Permissions on. I have read a lot of different things on Runtime Permissions, but I just can't seem to wrap my head around all the different snippets. Nothing I have found actually shows how to implement this into an existing Activity.
Other Points
When I run my existing application targeting SDK v23 I get the permission error as expected, but the permission error I get is not even a permission that I am requesting. I have the SEND_SMS permission in the Manifest file, but the error I am getting is for READ_SMS. My app runs fine on pre 6.0 without READ_SMS.
I would like the my app to ask for permission as soon as the app is launched because the sole purpose of the app is the send an SMS message, so without that permission there is no other use for the app.
Questions:
How would I implement Runtime Permissions for SEND_SMS into my existing Activity as soon as the app is launched?
Does the handling of these permission need to run in a background thread?
Do I also need permissions for READ_SMS since that is the permission error that it is giving (even though that permission has never been used on my app)?
My Existing Activity:
public class MainActivity extends Activity implements OnClickListener {
SimpleCursorAdapter mAdapter;
AutoCompleteTextView txtContract;
EditText txtTrip;
EditText txtDate;
Button btnSend;
Button btnUpdate;
String today;
String SENT = "SMS_SENT";
String DELIVERED = "SMS_DELIVERED";
private static final String API_KEY = "abcxyz";
private static final String CONTRACT_REGEX = "^([a-zA-Z0-9_-]){5}$";
private static final String TRIP_REGEX = "^([a-zA-Z0-9_-]){1,10}$";
private static final String DATE_REGEX = "^\\d{2}\\/\\d{2}\\/\\d{4}$";
private static final String PHONE_NUMBER = "1234567890";
private static final String DATE_FORMAT = "MM/dd/yyyy";
private BroadcastReceiver sendBroadcastReceiver;
private BroadcastReceiver deliveryBroadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TODO - IMPLEMENT RUNTIME PERMISSIONS FOR ANDROID >= 6.0
try {
// Initialize Views
txtContract = (AutoCompleteTextView) findViewById(R.id.txtContract);
txtTrip = (EditText) findViewById(R.id.txtTrip);
txtDate = (EditText) findViewById(R.id.txtDate);
btnSend = (Button) findViewById(R.id.btnSend);
btnUpdate = (Button) findViewById(R.id.btnUpdate);
// Set Listeners
txtDate.setOnClickListener(this);
btnSend.setOnClickListener(this);
btnUpdate.setOnClickListener(this);
// Set Date To Today And Format
final Calendar td = Calendar.getInstance();
int tYear = td.get(Calendar.YEAR);
int tMonth = td.get(Calendar.MONTH);
int tDay = td.get(Calendar.DAY_OF_MONTH);
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH);
td.set(tYear, tMonth, tDay);
today = sdf.format(td.getTime());
txtDate.setText(today);
// Check If Device Is Capable Of Sending SMS
PackageManager pm = this.getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) &&
!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA)) {
Toast.makeText(this, "Sorry, your device probably can't send SMS...",
Toast.LENGTH_SHORT).show();
}
// Send Receiver
sendBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), "Requesting trip...", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(getBaseContext(), "Generic failure", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(getBaseContext(), "No service", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(getBaseContext(), "Null PDU", Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(getBaseContext(), "Radio off", Toast.LENGTH_SHORT).show();
break;
}
}
};
// Delivery Receiver
deliveryBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), "Trip request successful.", Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
Toast.makeText(getBaseContext(), "Trip request failed.", Toast.LENGTH_SHORT).show();
break;
}
}
};
// Register Receivers
registerReceiver(deliveryBroadcastReceiver, new IntentFilter(DELIVERED));
registerReceiver(sendBroadcastReceiver , new IntentFilter(SENT));
// Set Up Adapter For Autocomplete
initializeAutoCompleteAdapter();
}
catch (Exception ex) {
Toast.makeText(this, "Error in MainActivity.onCreate: " + ex.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onDestroy() {
unregisterReceiver(sendBroadcastReceiver);
unregisterReceiver(deliveryBroadcastReceiver);
super.onDestroy();
}
// Auto Complete Adapter
public void initializeAutoCompleteAdapter() {
// Set Database Handler
final DBHelper DBHelper = new DBHelper(getBaseContext());
// Set Up Adapter For Autocomplete (This does not run on the main UI thread)
mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null,
new String[] { "contract" },
new int[] {android.R.id.text1},
0);
txtContract.setAdapter(mAdapter);
mAdapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
#Override
public CharSequence convertToString(Cursor cursor) {
final int colIndex = cursor.getColumnIndexOrThrow("contract");
return cursor.getString(colIndex);
}
});
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence description) {
String strContract = txtContract.getText().toString();
return DBHelper.getContract(strContract);
}
});
}
// OnClickListener Handler
#Override
public void onClick(View v) {
// Handle Clicked View
switch (v.getId()) {
// Date Field
case R.id.txtDate:
// Get Current Date
final Calendar c = Calendar.getInstance();
c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH),c.get(Calendar.DAY_OF_MONTH),0,0,0);
int mYear = c.get(Calendar.YEAR);
int mMonth = c.get(Calendar.MONTH);
int mDay = c.get(Calendar.DAY_OF_MONTH);
// Set Up DatePicker Dialog
DatePickerDialog datePickerDialog = new DatePickerDialog(this,
new DatePickerDialog.OnDateSetListener() {
#Override
public void onDateSet(DatePicker view, int year, int month, int day) {
// Define A New Calendar For Formatting
final Calendar cf = Calendar.getInstance();
// Format Selected Date
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH);
cf.set(year,month,day);
String selectedDate = sdf.format(cf.getTime());
// Add Selected Date To EditText Field
txtDate.setText(selectedDate);
}
}, mYear, mMonth, mDay);
// Set Max Date
c.add(Calendar.DATE, 2);
c.add(Calendar.SECOND, -1);
datePickerDialog.getDatePicker().setMaxDate(c.getTimeInMillis());
// Set Min Date
c.add(Calendar.DAY_OF_MONTH,-5);
c.add(Calendar.SECOND, 1);
datePickerDialog.getDatePicker().setMinDate(c.getTimeInMillis());
// Display DatePicker
datePickerDialog.show();
break;
// Submit Button
case R.id.btnSend:
Boolean rval = true;
if (!Validation.isValid(txtContract, CONTRACT_REGEX, "Invalid Contract #", true)) rval = false;
if (!Validation.isValid(txtTrip, TRIP_REGEX, "Invalid Trip #", true)) rval = false;
if (!Validation.isValid(txtDate, DATE_REGEX, "Invalid Date", true)) rval = false;
if(rval) {
new ValidateAndSend(this).execute();
}
break;
// Update Contract DB
case R.id.btnUpdate:
TelephonyManager tMgr = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
String mPhoneNumber = tMgr.getLine1Number();
new POSTAsync(this).execute(API_KEY, mPhoneNumber);
break;
}
}
// Validate And Send
class ValidateAndSend extends AsyncTask<String, String, Boolean>{
private final WeakReference<MainActivity> MainActivityWeakRef;
public ValidateAndSend(MainActivity mainActivity) {
super();
this.MainActivityWeakRef = new WeakReference<>(mainActivity);
}
// Define Variables
String strContract = txtContract.getText().toString();
String strTrip = txtTrip.getText().toString();
String strDate = txtDate.getText().toString();
String strMessage = strContract.concat("|").concat(strTrip).concat("|").concat(strDate);
Boolean rval = true;
#Override
protected void onPreExecute() {
}
#Override
protected Boolean doInBackground(String... contract) {
DBHelper DBHelper = new DBHelper(MainActivity.this);
if (DBHelper.validateContract(strContract) < 1) rval = false;
return rval;
}
#Override
protected void onPostExecute(Boolean rval){
if(rval){
// Hide Keyboard
View view = MainActivity.this.getCurrentFocus();
if(view != null){
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
if (MainActivityWeakRef.get() != null && !MainActivityWeakRef.get().isFinishing()) {
// Confirm Details
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setTitle("Confirm Trip");
alert.setMessage("CONTRACT: " + strContract + "\nTRIP: " + strTrip + "\nDATE: " + strDate);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Send SMS
sendSMS(PHONE_NUMBER, strMessage);
// Clear Fields
txtContract.setText("");
txtTrip.setText("");
txtDate.setText(today);
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Cancelled
}
});
// Show Alert
alert.show();
}
}
else{
txtContract.setError("Invalid contract #");
Toast.makeText(MainActivity.this, "You may need to update contracts.",
Toast.LENGTH_LONG).show();
}
}
}
// Send SMS
private void sendSMS(String phoneNumber, String message) {
String SENT = "SMS_SENT";
String DELIVERED = "SMS_DELIVERED";
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0, new Intent(DELIVERED), 0);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);
}
}
The runtime permission model for Android 6.0 is mainly divided into part
1. Checking Permission
2. Requesting Permission
you can create two method for this thing in your activity, As follow
Check Permission
private boolean checkPermission(){
int result = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
Request Permission
private void requestPermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,Manifest.permission.READ_SMS)){
Toast.makeText(context,"Read Sms Allowed.",Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.READ_SMS},PERMISSION_REQUEST_CODE);
}
}
Last but not least you need to override the onRequestPermissionsResult method
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Snackbar.make(view,"Permission Granted, Now you can access SMS.",Snackbar.LENGTH_LONG).show();
} else {
Snackbar.make(view,"Permission Denied, You cannot access SMS.",Snackbar.LENGTH_LONG).show();
}
break;
}
}
as you asked do i need to run this in thread .. answer is No Just do this in main thread
If you want to do less code then, please use Dexter is an Android library that simplifies the process of requesting permissions at runtime.
I am writing app to schedule SMS from alarm Manager. It works for me only one time and second time onwards it generate the multiple SMS.
Times are saved in SQL LITE and after send a SMS from Broadcast receiver read the DB and set the next alarm.
if 1 SMS has sent, second time it sends 2 SMS. next time 3 sms, and so on. I am using AmarmManager array and PendingIntents array to set alarm.
here is my coding... Please elp me... i am spending fer day for this taks..
public void SetAlarm(MessageInfo info, long delay, int amcount)
{
try
{
AlarmMSGInfo = info;
SaveMSGINFOPreference();
//Save Sent Status to Preference..
//savePreferences("SENT", old);
// register the alarm broadcast here
AMCount = amcount;
registerReceiver(mReceiver, new IntentFilter("com.rememberme.rm") );
//pendingIntent = PendingIntent.getBroadcast( this, 0, new Intent("com.techblogon.alarmexample"),0 );
pendingIntent[amcount] = PendingIntent.getBroadcast( RememberMe.this,amcount, new Intent("com.rememberme.rm"),PendingIntent.FLAG_ONE_SHOT );
alarmManager[amcount] = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
alarmManager[amcount].set( AlarmManager.RTC_WAKEUP, delay , pendingIntent[amcount] );
}
catch(Exception e)
{
//Toast.makeText(RememberMe.this, e.toString(), Toast.LENGTH_LONG).show();
Toast.makeText(RememberMe.this, "Alarm cannot be set...", Toast.LENGTH_LONG).show();
}
}
This is my Broadcast receiver ..
private void RegisterAlarmBroadcast()
{
//This is the call back function(BroadcastReceiver) which will be call when your
//alarm time will reached.
mReceiver = new BroadcastReceiver()
{
private static final String TAG = "Alarm Example Receiver";
#Override
public void onReceive(Context context, Intent intent)
{
String s = intent.getAction().toString();
if(intent.getAction() != null )
{
Log.i(TAG,"BroadcastReceiver::OnReceive() >>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
//Toast.makeText(context, "Congrats!. Your Alarm time has been reached", Toast.LENGTH_LONG).show();
MessageInfo temp= LoadMSGINFOPreference();
if(temp == null )
{
}
else
{
String snt = loadSavedPreferences("SENT");
if(snt== "")
Sent = 0;
else
Sent = Integer.valueOf(snt);
int status = 0;
if(Sent == 0)
{
//MessageInfo SentInfo = dbHandler.Get_MessageInfo(Sent);
//status = SentInfo.getStatus();
//}
//Toast.makeText(RememberMe.this, String.valueOf(msgType) , Toast.LENGTH_LONG).show();
//if(status == 0)
//{
if(temp.getMSGType() == 1)
{
_Recipients = ReadPhoneNumbers(temp.getRecipients());
_Message = temp.getMessage();
for(String number:_Recipients)
{
try
{
String num = number;
//Toast.makeText(context, "Congrats!. Your Alarm time has been reached : " + num + ":", Toast.LENGTH_LONG).show();
sendSMS(num, _Message);
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(), e.toString(),Toast.LENGTH_LONG).show();
//Toast.makeText(getApplicationContext(),"SMS faild, please try again later!",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
alarmManager[AMCount].cancel(pendingIntent[AMCount]);
}
//Updaate te record to set status = 1...(SEND)
temp.setStatus(1);
dbHandler.Update_MessageInfo(temp);
savePreferences("SENT", String.valueOf(temp.getID()));
//take nearest Record from da DB.
MessageInfo minfo = new MessageInfo();
ArrayList<MessageInfo> msgInfo_array_from_db = dbHandler.Get_MessageInfos();
if(msgInfo_array_from_db.size() > 0)
{
minfo = GetLatestMSGInfo(msgInfo_array_from_db);
//Set tat record to alarm manager...
SetAlarm(minfo, minfo.getDelay(), temp.getID());
}
//}
}
}
};
}
private void SaveMSGINFOPreference()
{
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
Editor prefsEditor = sp.edit();
Gson gson = new Gson();
String json = gson.toJson(AlarmMSGInfo);
prefsEditor.putString("AlarmMSGInfo", json);
prefsEditor.commit();
}