Checking if a new SMS has been read - android

I am working on a simple app for the HTC EVO that blinks the alternate notification LED when a new text message is received. I have this part working great via a Broadcast Receiver but I need some way to turn the LED off when the user has read the message(s) using their default SMS app. I'm not sure if it is best to do this in the receiver or in a background service. I found this, which might be what I am looking for, but I have no idea on how to use it as I could not find any instructions or tutorials.

Alright, I have worked out the following code which I think will meet my needs.
private int getUnreadSMSCount()
{
int count = 0;
Uri smsURI = Uri.parse("content://sms");
ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(smsURI, null, "read=0", null, null);
if (cursor != null)
{
try
{
count = cursor.getCount();
}
finally
{
cursor.close();
}
}
return count;
}

Unfortunately I do not believe there is a way to do this.
When your BroadcastReceiver receives the Intent it is a copy of the Intent, same with the default SMS app. So you each have copies of the message independent of eachother.
You can set your own copy of the message to read, but you will be unable to see its status in the default SMS app. Also, the default app does not send out a broadcast that the message has been read, all that data is kept locally.
The only way you would be able to implement this would be to write a full replacement of the Messaging app.
Sorry, I hope this helps, let me know if you have any other questions.

Related

Not able to read Service messages using READ_SMS permission android

We have an Android app where we are trying to read all the messages available in the phone. We are using READ_SMS permission but we are not able to read service messages in this way. By service mesaage I mean the messages obtained from different companies. For example I have messages in my phone from Amazon and Paytm but I am not able to load these while loading messages. I don't understand the issue. Is there any default filter that android is applying when the SMS get loaded or is there any issue with the code?
I use the following code to load all SMS:
private ArrayList load_sms(){
ContentResolver contentResolver = getContentResolver();
ArrayList<String> smsList = new ArrayList<>();
Cursor smsInboxCursor =
contentResolver.query(Uri.parse("content://sms/inbox"),
null,null,null,null);
int indexBody = smsInboxCursor.getColumnIndex("body");
int indexAddress = smsInboxCursor.getColumnIndex("address");
if(indexBody < 0 || !smsInboxCursor.moveToFirst())
return null;
do{
smsList.add("SMS From: " +
smsInboxCursor.getString(indexAddress) + " \nMessage: "
+ smsInboxCursor.getString(indexBody));
}while (smsInboxCursor.moveToNext());
return smsList;
}
So, the solution was quite vague. I have a MI phone and found that MI blocks service messages. To view those SMS' I had to give the permission manually from settings as given in this link: Can't read service messages in Redmi Note 3
When I ran my app on some other phone like in Samsung, I was able to view all the messages.

clear missed calls and clear notification from android bar

Using this code I managed to mark all missed calls as read:
ContentValues values = new ContentValues();
values.put(Calls.NEW, 0);
if (android.os.Build.VERSION.SDK_INT >= 14) {
values.put(Calls.IS_READ, 1);
}
StringBuilder where = new StringBuilder();
where.append(Calls.NEW);
where.append(" = 1 AND ");
where.append(Calls.TYPE);
where.append(" = ?");
context.getContentResolver().update(Calls.CONTENT_URI, values, where.toString(),
new String[]{ Integer.toString(Calls.MISSED_TYPE) });
but in the android notification bar I still have a flag with missed calls. How can I also clear the notification bar for calls in android?
How can I also clear the notification bar for calls in android?
You don't. That Notification is put there by another app, and you have no means of controlling whether that Notification is displayed, short of building a ROM mod that changes the behavior of that other app.
UPDATE: Since this answer was originally written, NotificationListenerService was added and can clear notifications, but only on Android 4.3+.
The only "legal" but extremely ugly and usually useless way to achieve what you want is to show Call Log to user. And I mean literally show (becomes visual, gets focus). In case you want to do this, here's how:
public static boolean showCallLog(Context context)
{
try
{
Intent showCallLog = new Intent();
showCallLog.setAction(Intent.ACTION_VIEW);
showCallLog.setType(android.provider.CallLog.Calls.CONTENT_TYPE);
context.startActivity(showCallLog);
return true;
}
catch (Exception e)
{
Log.d("Couldn't show call log.", e.getMessage());
}
return false;
}
The reason behind this mess is the fact that apps authoritatively responsible for call logging and notifying users about missed calls (stock phone apps) use cached values. Why? Because of overall performance. You need to somehow notify those apps that Call Log has changed (seen means changed, as well) and that it should update it. It would be nice if all such apps on all devices would receive a broadcast in order to refresh, but as far as I know, it's not the case.
I hope someone will find a better way (without interrupting the user) to force refresh on stock phone apps.

Observing changes in Android content observer for Audio.Media.EXTERNAL_CONTENT_URI

I am developing an Android app in which I have to detect changes in Android SD card for audio files with the file name, file path and operation performed upon it. Example if I am adding a file in my SD card then I want to know
Name of the file which is added
Path of the file
Operation -- Add
Previously I Have tried file observer But for that I have to apply it on each and every directory. So I searched for some other solution and got the info about Audio.Media.EXTERNAL_CONTENT_URI. Then I created a content observer like this
UriObserver.java -- which is a content observer
class UriObserver extends ContentObserver {
public UriObserver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
#Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
super.onChange(selfChange);
Log.d("INSTANT", "GETTING CHANGES");
}
}
This is the code for registration for it
UriObserver observer = new UriObserver(new Handler());
Log.d("INSTANT", "registered content observer");
this.getApplicationContext()
.getContentResolver()
.registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false,
observer);
Log.d("INSTANT", "registered content observer");
It let me know that some change has been occur in sdcard related to audio files. But it doesn't gives any sort of info about which file has been added, edited or deleted.
Then I searched for for solution and got this post
Android: How to detect a change in MediaStore when connected over MTP
In this post some code is given by Bhiefer as an answer which I think it could work, so I tried to implement that but I am not able to do so.
What can I do for this?
Update
Can I query Audio.Media.EXTERNAL_CONTENT_URI for its latest changes? This code:
mCursor = context.getContentResolver().query(
Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, "_id");
mCursor.moveToLast();
doesn't give the latest changes. Is there any other method to get the latest changes?
Let me try to unwind
ContentObserver
It doesn't give you information on what has changed
It's per design. Nothing in documentation says that it will give you this info.
FileObserver
It isn't recursive
Yes. It's know issue. What is the problem with iterating through all directories and setting observers? Per my understand by default there shouldn't be many (let say a dozen or so).
Android: How to detect a change in MediaStore when connected over MTP
The code which you found is just ContentObserver wrapped in UriObserver.
It does several things
He gets a cursor for one of content provides (in his case I believe it's images from MediaStore)
He registers an observer for this
As soon as some changes happens it forward this changes to external listener
However, this solution has two limitation:
It has inherit problem of ContentObserver that it doesn't report what happened to the data.
I believe it will report only changes to files which are registered in this MediaStore content provider. I believe system scans only special directories on SD card to check for images and so on. So, if a file will be places in some another directory, this solution won't see it.
So, What was your question about his code?
Summary
In the case, if you want to know exact type of changes for ALL files on scdard, I don't think that you can find anything better than FileObserver
Update 1
Couple more ideas, which may be not suitable for you. If you can root a device then you have the option to write filter driver for a filesystem, so your driver will be called each time when something has changed.
You can take a look at this link:
http://www.gossamer-threads.com/lists/linux/kernel/355190
Or you can reuse some existing linux changes notifications systems. As example, look at this:
http://stefan.buettcher.org/cs/fschange/. However, it could be that FileObserver is based exactly on it.
Anyway, both these approaches are low level and will require more time to figure out.
You can get the latest additions/modifications by querying on the DATE_ADDED and DATE_MODIFIED columns, but you will NOT get DELETIONS.
Here is how I do it:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
long lastDatabaseUpdateTime = preferences.getLong("lastDatabaseUpdateTime", 0);
long newDatabaseUpdateTime = (new Date()).getTime();
String[] cols = new String[] {MediaStore.Audio.Media._ID /* and other columns */};
String where = "("+MediaStore.MediaColumns.DATE_ADDED + ">" + (lastDatabaseUpdateTime/1000);
where += " or " + MediaStore.MediaColumns.DATE_MODIFIED + ">" + (lastDatabaseUpdateTime/1000);
where += ") and "+MediaStore.Audio.AudioColumns.IS_MUSIC+"==1 ";
Cursor cursor = MusicUtils.query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, cols, where, null, null);
/* Do my work on the cursor and close the cursor */
//If no exceptions, then save the new timestamp
SharedPreferences.Editor editor = preferences.edit();
editor.putLong("lastDatabaseUpdateTime", newDatabaseUpdateTime);
editor.commit();

Android - Is it possible to have a content provider of hardware interacting methods?

The company I work for is made a custom piece of hardware that runs Android. It will be connected to quite a few peripheral components. A key point is that this device is for another company.
I know with a ContentProvider, data can be shared between applications. However, what I am wondering is whether methods that interact with the hardware (GPIO interaction) can be stored in some way that they can be used by any application.
For example, say the device has a certain GPIO pin mapped to an LED. You create a method that makes the LED flash, you use it in your application, then give the device to someone else and want the code hidden but use the LED flashing method again. This is not necessary but could allow the other company to build another app complementing the one we provide with the device.
Any insight would helpful.
Cheers
You can use ContentProvider like a REST webinterface
From apps:
Uri ledUri = Uri.parse("content://your.app/led");
ContentResolver cr = getContentResolver();
// "write" data
ContentValues cv = new ContentValues();
cv.put("state", 1);
cr.insert(ledUri, cv);
// read data
int newState = 0;
Cursor c = cr.query(ledUri, new String[] { "state" }, null, null, null);
if (c.moveToFirst()) {
newState = c.getInt(0);
}
Inside your provider, instead of writing data into a database you simply set / read GPIO states. Roughly like
#Override
public Uri insert(Uri uri, ContentValues values) {
if (uri.toString().equals("content://your.app/led")) {
int requestedState = values.getAsInteger("state");
set_gpio_state(requestedState);
}
}
How to acccess GPIOs from Java is another question since they are (AFAIK) only accessible on kernel level.

Is it possible to count the number of times I open google?

I want to develop an application (or service) that will count the number of times I open http://www.google.com url. But I do not know if this is possible with Android.
I want to do a research on this field but I do not know how to start. As far I was looking, there is no intent fired when some uri in the browser is oppened, but I guess there is so way to do this. I do not expect to be simple but I hope it is possible. My hope is the fact that some applications measure the network traffic, meaning everything is somehow tracked.
This isn't guaranteed to work across all flavours of Android, but according to the documentation you can read the browser database.
Browser is a static helper that provides access to the bookmarks database and, handily for your requirements, also exposes browser history via a method called getAllVisitedUrls.
Cursor cursor=Browser.getAllVisitedUrls(getContentResolver());
cursor.moveToFirst();
int occasions=0;
while (cursor.moveToNext()) {
String urlVisited=cursor.getString(cursor.getColumnIndex(BookmarkColumns.URL));
if (urlVisited.contains("www.google.")) {
occasions++;
}
Log.d("History",cursor.getString(cursor.getColumnIndex(BookmarkColumns.URL)));
}
Log.d("History","occasions="+occasions);
EDIT: Sorry to update this after it's been accepted as an answer, but contrary to what I initially wrote you can indeed register to listen for changes to the bookmarks URI:
getContentResolver().registerContentObserver(Browser.BOOKMARKS_URI, true,
new ContentObserver(new Handler()) {
#Override
public void onChange(boolean selfChange) {
Log.d("History","Bookmarks has changed");
super.onChange(selfChange);
}
});
I hope that's helpful.
EDIT: I neglected to mention that you need to add a permission to your manifest: com.android.browser.permission.READ_HISTORY_BOOKMARKS

Categories

Resources