I am trying to download an Android app from a server using the DownloadManager class, install it and then detect when the installation is completed. I am using two receivers: one to detect the download process and the other to detect the install process. The first receiver works properly, but the second doesn't. What I am doing wrong?
DownloadManager dm = (DownloadManager) DownloadApplicationActivity.this.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request req = new DownloadManager.Request(Uri.parse(MY_LINK));
req.setTitle(MY_TITLE)
.setDescription("Downloading ....")
// download the package to the /sdcard/downlaod path.
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
MY_PATH);
long enqueue = dm.enqueue(req);
BroadcastReceiver receiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
Query query = new Query();
query.setFilterById(enqueue);
Cursor c =dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
// show a notification bar.
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon,"",System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.flags |= Notification.FLAG_NO_CLEAR;
Intent i = new Intent(Intent.ACTION_VIEW);
// when the notification is clicked, install the app.
i.setDataAndType(Uri.fromFile(new File(Environment
.getExternalStorageDirectory() + APP_PATH)),"application/vnd.android.package-archive");
PendingIntent pendingIntent = PendingIntent.getActivity(
activity, 0, i, 0);
notification.setLatestEventInfo(activity, MY_TEXT, MY_TEXT,pendingIntent);
notification.number += 1;
notificationManager.notify( 0, notification);
//i want to detect the app's installation, I register a ne receiver
registerReceiver(installReceiver,new IntentFilter(Intent.ACTION_PACKAGE_ADDED));
}
}
};
BroadcastReceiver installReceiver= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
Uri data = intent.getData();
String packageName = data.getEncodedSchemeSpecificPart();
Log.i("The installed package is: ", "" + packageName);
}
}
};
I solved my problem, I added
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_INSTALL);
intentFilter.addDataScheme("package");
before the line :
registerReceiver(installReceiver, intentFilter);
You can try the code below. This way you can get all activities that can be called by an intent and if you know the activity name and it is present in list retrieved by queryIntentActivities()..you know it is installed.
public void callQrScan()
{
Intent intent1 = new Intent("com.google.zxing.client.android.SCAN");
if(isCallable(intent1)== true){
Context context = getApplicationContext();
CharSequence text = "Scan Niet Gelukt";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
else{
Context context = getApplicationContext();
CharSequence text = "Scan Niet Gelukt";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
Button tempbutton = (Button)findViewById(R.id.Button03);
tempbutton.setOnClickListener(new OnClickListener()
{
public void onClick(final View v)
{
callQrScan();
}
});
}
private boolean isCallable(Intent intent1) {
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent1,
PackageManager.MATCH_DEFAULT_ONLY);
if(list.size() > 0)
return true ;
else
return false;
}
Hope it helps :)
Related
I know there are some libraries for this, but i want to implement my own pause/resume functionality for android.
i'm now using DownloadManager for downloading and this is the service i implemented for download:
public class DownloadService extends Service {
public static boolean isServiceRunning = false;
private static String downloadingPackageName;
private DownloadManager downloadManager;
long downloadRef;
RemoteViews contentView;
private boolean isDownloading = false;
Notification notification;
NotificationManager manager;
DownloadRequestListener downloadRequestListener;
NotificationManager notifManager;
private String dirPath;
private String packageName;
public static String PACKAGE_NAME;
#Override
public void onCreate() {
super.onCreate();
PACKAGE_NAME = getApplicationContext().getPackageName();
Log.e("OnCreate","OnCreateCommandClled...");
downloadRequestListener = new DownloadRequestListener();
IntentFilter filter = new IntentFilter("ir.amulay.downloadRequest");
registerReceiver(downloadRequestListener, filter);
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
isServiceRunning = true;
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Log.e("Service","Service Destroyed...");
unregisterReceiver(downloadRequestListener);
isServiceRunning = false;
super.onDestroy();
}
public Long downloadFile(String path, String packageName, String dirPath){
if(isDownloading) return null;
isDownloading =true;
this.dirPath = dirPath;
notifManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
contentView = new RemoteViews(getPackageName(), R.layout.download_notification_bar);
contentView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
contentView.setTextViewText(R.id.title, "Custom notification");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChanel = new NotificationChannel(
"downloadChanel",
"Example Service Chanel",
NotificationManager.IMPORTANCE_LOW
);
manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChanel);
}
notification = new NotificationCompat.Builder(this,"downloadChanel")
.setContentTitle("test")
.setContentText("test Againg")
.setContent(contentView)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setAutoCancel(false)
.build();
startForeground(1,notification);
//I Dont Want many files to be downloaded at same time, so here is a check...
downloadingPackageName = packageName;
Uri uri = Uri.parse(path);
//Uri dir = Uri.parse(dirPath + "/" + packageName + ".apk");
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
this.packageName = packageName;
request.setTitle("Download File");
request.setDestinationInExternalPublicDir(dirPath, packageName+".apk");
request.setDescription("download apk files using download manager");
request.setMimeType(getMimeType(uri.toString()));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setVisibleInDownloadsUi(false);
// request.setDestinationUri(dir);
request.setAllowedOverMetered(true);
request.setAllowedOverRoaming(true);
downloadRef = downloadManager.enqueue(request);
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
boolean downloading = true;
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadRef); //filter by id which you have receieved when reqesting download from download manager
Cursor cursor = manager.query(q);
if(cursor.getCount() <= 0 ){
return;
}
cursor.moveToFirst();
//if its Running Send BroadCast... :)
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_RUNNING) {
int bytes_downloaded = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
final int dl_progress = (int) ((bytes_downloaded * 100L) / bytes_total);
Log.e("DownloadProgress", "progress= " + dl_progress);
contentView.setTextViewText(R.id.title,"Downloading " +dl_progress);
// contentView.setProgressBar(R.id.downloadProgress,200,dl_progress,true);
notification.contentView.setProgressBar(R.id.downloadProgress, 100, dl_progress, false);
notifManager.notify(1, notification );
Intent intent = new Intent();
intent.setAction("ir.amulay.downloadEvent");
intent.putExtra("eventType","downloadProgress");
intent.putExtra("progresspercent",""+dl_progress);
intent.putExtra("packagename",packageName);
intent.putExtra("refID",""+downloadRef);
sendBroadcast(intent);
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
downloading = false;
}
cursor.close();
if(!downloading) {
Intent intent= new Intent();
intent.setAction("ir.amulay.downloadEvent");
intent.putExtra("eventType","downloadCompleted");
intent.putExtra("packagename",packageName);
intent.putExtra("refID",""+downloadRef);
sendBroadcast(intent);
//send a broadcast to tell its completed
return;
}
handler.postDelayed(this,300);
}
});
return downloadRef;
}
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (downloadRef == id) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
openDownloadedAttachment(context, downloadId);
}
}
};
private String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
type = mime.getMimeTypeFromExtension(extension);
}
return type;
}
private void openDownloadedAttachment(final Context context, final long downloadId) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
String downloadLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
String downloadMimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
if ((downloadStatus == DownloadManager.STATUS_SUCCESSFUL) && downloadLocalUri != null) {
openDownloadedAttachment(context, Uri.parse(downloadLocalUri), downloadMimeType);
}
}
cursor.close();
}
private void openDownloadedAttachment(final Context context, Uri attachmentUri, final String attachmentMimeType) {
if(attachmentUri!=null) {
// Get Content Uri.
if (ContentResolver.SCHEME_FILE.equals(attachmentUri.getScheme())) {
// FileUri - Convert it to contentUri.
File file = new File(attachmentUri.getPath());
attachmentUri = FileProvider.getUriForFile(this, "com.freshdesk.helpdesk.provider", file);
}
Intent openAttachmentIntent = new Intent(Intent.ACTION_VIEW);
openAttachmentIntent.setDataAndType(attachmentUri, attachmentMimeType);
openAttachmentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
context.startActivity(openAttachmentIntent);
} catch (ActivityNotFoundException e) {
// Toast.makeText(context, context.getString("cant O"), Toast.LENGTH_LONG).show();
}
finally {
stopSelf();
}
}
}
private class DownloadRequestListener extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received", Toast.LENGTH_SHORT).show();
String reqType = intent.getStringExtra("reqType");
String packageName =intent.getStringExtra("package");
if(reqType.equals("download")){
String url = intent.getStringExtra("url");
String dirPath = intent.getStringExtra("dirPath");
downloadFile(url,packageName,dirPath);
}
else if(reqType.equals("stop")){
if(downloadingPackageName.equals(packageName) && downloadManager!= null){
downloadManager.remove(downloadRef);
isDownloading =false;
unregisterReceiver(onDownloadComplete);
stopSelf();
}
}
}
}
}
how can i implement Pause/Resume for my downloads? WITHOUT a library?
is it possible trough Download manager itself or i should use some other methods?
You can send message to the DownloadService you created, and invoke the DownloadManager to do the pause and resume action.
When DownloadManager enqueue a download task, you will get a id (long)
DownloadManager keep the download info in the ContentProvider, just update the ContentProvider info with the given id (long), if the network or other conditions satisfied the action will execute.
You can extends DownloadManager and create a pair of methods like below.
Pause Download
/**
* pause download
*
* #param ids the IDs of the downloads to be paused
* #return the number of downloads actually paused
*/
public int pauseDownload(long... ids) {
if (ids == null || ids.length == 0) {
// called with nothing to remove!
throw new IllegalArgumentException("input param 'ids' can't be null");
}
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CONTROL, Downloads.Impl.CONTROL_PAUSED);
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PAUSED_BY_APP);
if (ids.length == 1) {
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values,
null, null);
}
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
getWhereArgsForIds(ids));
}
Resume download
/**
* resume download
*
* #param ids the IDs of the downloads to be resumed
* #return the number of downloads actually resumed
*/
public int resumeDownload(long... ids) {
if (ids == null || ids.length == 0) {
// called with nothing to remove!
throw new IllegalArgumentException("input param 'ids' can't be null");
}
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CONTROL, Downloads.Impl.CONTROL_RUN);
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_RUNNING);
if (ids.length == 1) {
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values,
null, null);
}
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
getWhereArgsForIds(ids));
}
I have written code for downloading images through Intent Service
public class UIIntentService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
*/
public UIIntentService() {
super("UIIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
downLoadManager();
}
private void downLoadManager() {
// Starting download manager
final DownloadManager manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse("http://some_url/xyz.jpg"));
MainActivity.enqueue = manager.enqueue(request);
scheduleAlarm(MainActivity.enqueue);
}
public void scheduleAlarm(long id) {
Intent intent = new Intent(getBaseContext(), com.example.com.downloaddemo.DisplayInoker.class);
intent.putExtra("ID", ""+id);
final PendingIntent pIntent = PendingIntent.getBroadcast(getBaseContext(), com.example.com.downloaddemo.DisplayInoker.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
3000, pIntent);
}
}
My BroadcastReceiver for AlarmManager
public class DisplayInoker extends BroadcastReceiver{
public static final int REQUEST_CODE = 12345;
public static final String ACTION = "DISPLAYRESULT";
private long enqueue;
// Triggered by the Alarm periodically
#Override
public void onReceive(Context context, Intent intent) {
EventBus bus = EventBus.getDefault();
if(intent.getExtras().getString("ID") != null) {
enqueue = Long.parseLong("" + intent.getExtras().getString("ID"));
Log.d("Innnnnnnnnnnnnnnnnnnnnn", ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
final DownloadManager manager = (DownloadManager) context.getSystemService(context.DOWNLOAD_SERVICE);
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(enqueue);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
double bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
double bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
double percentComplete = 0;
// checking whether file downloaded or not
boolean downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
== DownloadManager.STATUS_SUCCESSFUL ? true : false;
cursor.close();
boolean stopDisplaying = false;
if (!downloaded) {
try {
percentComplete = (bytes_downloaded / bytes_total) * 100;
bus.post("" + (int) percentComplete);
} catch (Exception e) {
percentComplete = 0;
e.printStackTrace();
}
} else {
Log.d("completed", "////////////////////// end ///////////////////////////" + bytes_total + " " + bytes_downloaded);
percentComplete = (bytes_downloaded / bytes_total) * 100;
bus.post("" + (int) percentComplete);
}
}
}
}
Calling my Intent service simply
Intent intentservice = new Intent(MainActivity.this, UIIntentService.class);
startService(intentservice);
This code is working fine and I am receiving progress updates of single download operation.
Now, I want to use this IntentService to perform multiple download operations with progress update of each operation. can you please check whether is it possible through this code or provide some other alternative solution.
Thanks in advance.
Using Handler you can achieve the result.
Please see here.
Good day! I'm trying to install downloaded apk.I've uploaded it to
http://w194442.open.ge.tt/1/files/........?download
I download it by this code:
downloadUrl = urlStringChooser(myURL);
String downloadCompleteIntentName = DownloadManager.ACTION_DOWNLOAD_COMPLETE;
IntentFilter downloadCompleteIntentFilter = new
IntentFilter(downloadCompleteIntentName);
context = getApplicationContext();
context.registerReceiver(downloadCompleteReceiver, downloadCompleteIntentFilter);
String servicestring = Context.DOWNLOAD_SERVICE;
downloadmanager = (DownloadManager) getSystemService(servicestring);
Uri uri = Uri.parse(downloadUrl);
DownloadManager.Request request = new DownloadManager.Request(uri);
downloadID = downloadmanager.enqueue(request);
After that I get a broadcast signal from system that file downloaded :
private BroadcastReceiver downloadCompleteReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0L);
if (id != downloadID) {
private BroadcastReceiver downloadCompleteReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0L);
if (id != downloadID) {
Toast toast = Toast.makeText(getApplicationContext(), "downloadID FAIL", Toast.LENGTH_LONG);
toast.show();
return;
}
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
Cursor cursor = downloadManager.query(query);
if (!cursor.moveToFirst()) {
Toast toast = Toast.makeText(getApplicationContext(), "cursor.moveToFirst FAIL", Toast.LENGTH_LONG);
toast.show();
return;
}
int statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL != cursor.getInt(statusIndex)) {
Toast toast = Toast.makeText(getApplicationContext(), "cDownloadManager.STATUS_SUCCESSFUL != cursor.getInt(statusIndex)", Toast.LENGTH_LONG);
toast.show();
return;
}
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
uri = Uri.parse(downloadedPackageUriString);
if(uri != null) {
Toast toast = Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_LONG);
toast.show();
installUpdate(uri);
}
}
};
return;
}
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
Cursor cursor = downloadManager.query(query);
if (!cursor.moveToFirst()) {
Toast toast = Toast.makeText(getApplicationContext(), "cursor.moveToFirst
FAIL", Toast.LENGTH_LONG);
toast.show();
return;
}
int statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL != cursor.getInt(statusIndex)) {
Toast toast = Toast.makeText(getApplicationContext(),
"cDownloadManager.STATUS_SUCCESSFUL != cursor.getInt(statusIndex)",
Toast.LENGTH_LONG);
toast.show();
return;
}
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
uri = Uri.parse(downloadedPackageUriString);
if(uri != null) {
Toast toast = Toast.makeText(getApplicationContext(), "Success",
Toast.LENGTH_LONG);
toast.show();
installUpdate(uri);
}
}
};
Works fine for now. Then I call installUpdate(uri); to install it.
Intent promptInstall = new Intent(Intent.ACTION_VIEW);
promptInstall.setClass(context, MyActivity.class);
promptInstall.setDataAndType(goodUri,"application/vnd.android.package-archive");
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.d(TAG, "Before startActivity ");
startActivity(promptInstall);
And nothing happens. Logcat is
09-23 05:30:07.531 9492-9492/regulatory.securitycode.com.vpnupdate D/Updater﹕ Before
startActivity
09-23 05:30:07.556 9492-9492/regulatory.securitycode.com.vpnupdate E/dalvikvm﹕
dvmPauseGc(AppLaunch) called - cookie=0xf692 (f=0x1)
09-23 05:30:07.566 9492-9492/regulatory.securitycode.com.vpnupdate
E/MoreInfoHPW_ViewGroup﹕ Parent view is not a TextView
09-23 05:30:07.611 9492-9492/regulatory.securitycode.com.vpnupdate D/mali_winsys﹕
new_window_surface returns 0x3000
09-23 05:30:07.651 9492-9492/regulatory.securitycode.com.vpnupdate E/dalvikvm﹕
dvmResumeGc(0xf692, 0) called (f=0x1)
What do I do wrong?
Have you checked the "Install from Unknown sources" option in the Security Settings?
I have an app that creates multiple alarms. Everything works fine, however, for some other functions (like updating a log) I need to retrieve the alarmID when the alarm is fired.
Here is the code the alarms are set with:
public void setAlarm(){
Intent intentAlarm = new Intent(c,AlarmReceiver.class);
intentAlarm.putExtra("userid", userid);
// create the object
AlarmManager alarmManager = (AlarmManager)
c.getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent;
alarmIntent = PendingIntent.getActivity(c, alarmID, intentAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,timeToMiliseconds(hour,minute),
AlarmManager.INTERVAL_DAY,alarmIntent);
Toast.makeText(c,"Alarm set for " + toTime(hour,minute),Toast.LENGTH_SHORT).show();
Log.d("setAlarm()",alarm.toString());
}
The alarm receiver is an activity (which works fine). I just need to retrieve the alarms ID that's currently being fired.
public class AlarmReceiver extends Activity {
private MediaPlayer mMediaPlayer;
private String scanContent;
private static final int ZBAR_SCANNER_REQUEST = 0;
String userid;
Button backBtn;
private PowerManager.WakeLock wakelock;
private ListView medBoxList;
ArrayList<HashMap<String, String>> medList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm);
ActionBar actionBar = getActionBar();
actionBar.hide();
/**
* Wakeup device if it's sleeping
*/
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Tag");
wakelock.acquire();
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
Intent alarmActivityIntent = getIntent();
userid = alarmActivityIntent.getStringExtra("userid");
playSound(this, getAlarmUri());
Toast.makeText(this, "Take Medication", Toast.LENGTH_LONG).show();
Button stopAlarm = (Button) findViewById(R.id.scanQR);
Button skipBtn = (Button) findViewById(R.id.skipBtn);
backBtn = (Button)findViewById(R.id.backBtn);
//Click button to scan and update userlog
//Click button to scan and update userlog
stopAlarm.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
mMediaPlayer.stop();
launchQRScanner();
}
});
//Click button to skip
skipBtn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
mMediaPlayer.stop();
}
});
}
private void playSound(Context context, Uri alert) {
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.setDataSource(context, alert);
final AudioManager audioManager = (AudioManager) context
.getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
} catch (IOException e) {
System.out.println("OOPS");
}
}
//Get an alarm sound. Try for an alarm. If none set, try notification,
//Otherwise, ringtone.
private Uri getAlarmUri() {
Uri alert = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (alert == null) {
alert = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if (alert == null) {
alert = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
}
}
return alert;
}
public void launchQRScanner() {
mMediaPlayer.stop();
Intent intent = new Intent(this, ZBarScannerActivity.class);
intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mMediaPlayer.stop();
scanContent = data.getStringExtra(ZBarConstants.SCAN_RESULT);
finish();
if(scanContent != null){
updateUserLog(scanContent);
Intent nextScreen = new Intent(getApplicationContext(),UserlogListActivity.class);
startActivity(nextScreen);
}
}
//Disable alarm with button instead of scan
public void alarmStopper(View v){
mMediaPlayer.stop();
Intent nextScreen = new Intent(getApplicationContext(),UserlogListActivity.class);
startActivity(nextScreen);
}
//TAKE MED ACTIVITY (MOVE TO )
public void updateUserLog(String scanContent){
//Toast.makeText(this, "Adding Userlog = " + scanContent, Toast.LENGTH_SHORT).show();
if(scanContent != null){
String userid,medname,tabstaken,dob;
//Break the scan content into strings for each variable
StringTokenizer st = new StringTokenizer(scanContent, ",");
dob = st.nextToken();
medname = st.nextToken();
tabstaken = st.nextToken();
if(dob != "" && medname != "" && tabstaken != ""){
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
HashMap<String,String> userLog = new HashMap<String, String>();
HashMap<String,String> user = new HashMap<String, String>();
user = db.getUserDetails();
//Store the userlog by passing to UserLogEntry
userid = user.get("uid");
if(userid != ""){
userLog = db.getNewestUserLogEntryForMed(medname);
String tabstr = userLog.get("tabsleft");
Log.d ("getNewestUserLogEntryForMed()", "medname " + userLog.get("medname") + " timetaken "
+ userLog.get("medtaken") + " Tabs - " + tabstr);
int tabs = Integer.parseInt(tabstr);
tabs = tabs - 1;
String tabsupdated = Integer.toString(tabs);
Log.d ("Tabs Updated - ", "medname " + userLog.get("medname") + " timetaken "
+ userLog.get("medtaken") + " Tabs - " + tabsupdated);
UserLogEntry userlog = new UserLogEntry(getApplicationContext(),userid,medname,tabsupdated);
userlog.addUserLog();
finish();
}
}
}
}
Any tips?
Much appreciated
So the answer was staring me in the face. I can use bundle to pass whatever I need into the alarm intent. I already was passing the userid (incorrectly). I just have to remember whenever there is an intent, that I can use bundle to pass simple variables along with it.
Intent intentAlarm = new Intent(c,AlarmReceiver.class);
Bundle extras = new Bundle();
extras.putString("userid", userid);
extras.putInt("alarmID", alarmID);
extras.putString("userlogID", userlogID);
extras.putString("medname", medname);
intentAlarm.putExtras(extras);
I figured I'd answer my own question in case someone else needs to do something similar, but if this is not helpful a moderator can delete it.
I've create a broadcast receiver that listen to the android.provider.Telephony.SMS_RECEIVED event and creates its own notification.
I also use the same receiver in the app to update the activities when an sms is received using a callback.
The problem is that the sms app notification event is dispatched after my notification, so when I update the sms is not preset in content://sms
I would like to delay my notification if it's possible, can't find how to do it.
here's the code:
public class SmsReceiver extends BroadcastReceiver {
Context context;
int nmessages = 0;
#Override
public void onReceive(Context context, Intent intent) {
//—get the SMS message passed in—
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String messages = "";
this.context = context;
if (bundle != null)
{
//—retrieve the SMS message received—
Object[] smsExtra = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[smsExtra.length];
nmessages = SmsHolder.getNumberUnreadSms(context) +1;
for (int i=0; i<msgs.length; i++)
{
SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
//take out content from sms
String body = sms.getMessageBody().toString();
String address = sms.getOriginatingAddress();
messages += "SMS from " + address + " :\n";
messages += body + "\n";
putSmsToDatabase(sms, context );
}
//—display the new SMS message—
createNotification(SmsMessage.createFromPdu((byte[])smsExtra[0]), context);
updateActivity();
}
}
public void updateActivity(){
}
private void putSmsToDatabase( SmsMessage sms, Context context )
{
String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
// Create SMS row
ContentValues values = new ContentValues();
values.put("address", sms.getOriginatingAddress().toString() );
values.put("date", mydate);
values.put("body", sms.getMessageBody().toString());
// values.put( READ, MESSAGE_IS_NOT_READ );
// values.put( STATUS, sms.getStatus() );
// values.put( TYPE, MESSAGE_TYPE_INBOX );
// values.put( SEEN, MESSAGE_IS_NOT_SEEN );
}
private void createNotification(SmsMessage sms, Context context){
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String contentTitle;
if (nmessages < 2){
contentTitle = "SMS: " + ContactsInterface.getContactDisplayNameByNumber(sms.getOriginatingAddress(), context);
}else {
contentTitle = nmessages + " " + context.getResources().getString(R.string.new_messages);
}
// construct the Notification object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(contentTitle)
.setContentText(sms.getMessageBody())
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(getIconBitmap())
.setNumber(nmessages);
builder.setAutoCancel(true);
//(R.drawable.stat_sample, tickerText,
// System.currentTimeMillis());
// Set the info for the views that show in the notification panel.
//notif.setLatestEventInfo(this, from, message, contentIntent);
/*
// On tablets, the ticker shows the sender, the first line of the message,
// the photo of the person and the app icon. For our sample, we just show
// the same icon twice. If there is no sender, just pass an array of 1 Bitmap.
notif.tickerTitle = from;
notif.tickerSubtitle = message;
notif.tickerIcons = new Bitmap[2];
notif.tickerIcons[0] = getIconBitmap();;
notif.tickerIcons[1] = getIconBitmap();;
*/
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, Login.class);
// Because clicking the notification opens a new ("special") activity, there's
// no need to create an artificial back stack.
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
context,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Ritardo in millisecondi
builder.setContentIntent(resultPendingIntent);
// Note that we use R.layout.incoming_message_panel as the ID for
// the notification. It could be any integer you want, but we use
// the convention of using a resource id for a string related to
// the notification. It will always be a unique number within your
// application.
nm.notify(R.drawable.ic_drawer, builder.build());
}
private Bitmap getIconBitmap() {
BitmapFactory f = new BitmapFactory();
return f.decodeResource(context.getResources(), R.drawable.ic_sms);
}
}
If you just need to do it for a specific amount of time, probably the easiest way is to use a handler and use a postDelayed(). Something like this:
// SLEEP 5 SECONDS HERE ...
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// createNotification(SmsMessage.createFromPdu((byte[])smsExtra[0]), context);
updateActivity();
}
}, 5000);
If you want to wait for another action, that's a bit more complicated.