I am fed up of this issue, don't know actually where is problem, Below is my code :
private void readSMS() throws IOException {
// TODO Auto-generated method stub
Log.d("Read SMS","Called");
ContentResolver cr = context.getContentResolver();
Uri uri = Uri.parse("content://sms/inbox");
StringBuilder smsBackup = new StringBuilder();
Cursor messagesCursor = cr.query(uri, new String[] { "_id","address","body","person"}, null,null, null);
smsBackup.append("SMS Back UP (Total Message(s)::"+messagesCursor.getCount()+") \n\n");
String name = null;
if(messagesCursor.getCount() > 0){
while(messagesCursor.moveToNext()){
name = null;
name = getName(messagesCursor.getString(messagesCursor.getColumnIndex("address")));
if(name==null)
name = "Sender : " + messagesCursor.getString(messagesCursor.getColumnIndex("address"));
smsBackup.append("Sender : "+name +"\n"+ "Message : "+messagesCursor.getString(messagesCursor.getColumnIndex("body")) + "\n\n");
}
}
Log.d("InSMS Lenght","::"+smsBackup.toString().length());
}
here is log cat message : W/CursorWrapperInner(8375): Cursor finalized without prior close()
You should close the Cursor object once you're done working with it.
This may be old but here is the reason why.
Don't throw the exception here:
readSMS() throws IOException
instead wrap in a a try catch block like so:
try{
ContentResolver cr = context.getContentResolver();
Uri uri = Uri.parse("content://sms/inbox");
StringBuilder smsBackup = new StringBuilder();
Cursor messagesCursor = cr.query(uri, new String[] { "_id","address","body","person"}, null,null, null);
smsBackup.append("SMS Back UP (Total Message(s)::"+messagesCursor.getCount()+") \n\n");
String name = null;
if(messagesCursor.getCount() > 0){
while(messagesCursor.moveToNext()){
name = null;
name = getName(messagesCursor.getString(messagesCursor.getColumnIndex("address")));
if(name==null)
name = "Sender : " + messagesCursor.getString(messagesCursor.getColumnIndex("address"));
smsBackup.append("Sender : "+name +"\n"+ "Message : "+messagesCursor.getString(messagesCursor.getColumnIndex("body")) + "\n\n");
}
}
messagesCursor.close();
}catch(IOException e){
//handle here, if not log it
}finally{
//can also close here if you want, need to wrap in another try block and check for null
}
Seems like the problem is the ioexception is being caught before the close() could be called. The method is then thrown at that point and is never called. I could be wrong, I just took a quick glance at it. I hope this helps.
Related
I'm trying to get a specific file by its name using the following code, however, it looks like the selection arguments are ignored as it always returns the 1st file of the root tree
final ContentResolver resolver = mContext.getContentResolver();
final Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(mUri, DocumentsContract.getDocumentId(mUri));
Cursor c = null;
try {
c = resolver.query(childrenUri, new String[] { DocumentsContract.Document.COLUMN_DOCUMENT_ID }, DocumentsContract.Document.COLUMN_DISPLAY_NAME + " = ?", new String[] { displayName }, null);
if (c.moveToFirst()) {
final String documentId = c.getString(0);
final DocumentFile result = new TreeDocumentFile(this, mContext, DocumentsContract.buildDocumentUriUsingTree(mUri, documentId));
return result;
}
} catch (Exception e) {
Log.w(TAG, "Failed query: " + e);
} finally {
closeQuietly(c);
}
Basically the result is the same that the following query
c = resolver.query(childrenUri, new String[] { DocumentsContract.Document.COLUMN_DOCUMENT_ID }, null. null, null);
Any idea why?
I want to delete a single occurrence of a repeated event. This is my code:
private void handleActionDelete(long event, long occurrence) {
final ContentResolver contentResolver = getContentResolver();
Uri.Builder eventsUriBuilder = CalendarContract.Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(eventsUriBuilder, Long.MIN_VALUE);
ContentUris.appendId(eventsUriBuilder, Long.MAX_VALUE);
Uri eventsUri = eventsUriBuilder.build();
Cursor cursor;
String[] projection;
projection = new String[]{CalendarContract.Instances.BEGIN};
String selection = "Instances." + CalendarContract.Instances._ID + " = ? AND " + CalendarContract.Instances
.EVENT_ID + " = ?";
String[] selArgs = new String[]{Long.toString(occurrence), Long.toString(event)};
cursor = getContentResolver().query(eventsUri, projection, selection, selArgs, null);
if (cursor == null) {
return;
}
if (cursor.getCount() == 0) {
cursor.close();
return;
}
cursor.moveToFirst();
ContentValues values = new ContentValues();
values.put(CalendarContract.Events.ORIGINAL_INSTANCE_TIME, cursor.getLong(cursor.getColumnIndex
(CalendarContract.Instances.BEGIN)));
values.put(CalendarContract.Events.STATUS, CalendarContract.Events.STATUS_CANCELED);
Uri uri = Uri.withAppendedPath(CalendarContract.Events.CONTENT_EXCEPTION_URI, String.valueOf(event));
cursor.close();
try {
contentResolver.insert(uri, values);
} catch (Exception ignored) {
}
}
I already checked all other similar problems on stackoverflow but I didn't find any solution, maybe it's something related to my code, I hope someone can review it.
if you use com.google.api.services.calendar.Calendar I suppose you already have id of the event you want to delete
the answer is right there in the documentation and states (I've copied the exact snippet from doc):
// Initialize Calendar service with valid OAuth credentials
Calendar service = new Calendar.Builder(httpTransport, jsonFactory, credentials)
.setApplicationName("applicationName").build();
// Delete an event
service.events().delete('primary', "eventId").execute();
Recently, I have been working on an Android project that requires me to get the text from and MMS. I don't have a whole lot of experience with Android, but I am familiar with SQL and java and I have been following these posts as closely as possible.
Detecting MMS messages on Android
How to Read MMS Data in Android?
The code that I came up with mostly works, but it seems to always grab the text from the second most recent MMS message and not the most recent one. Any idea why this would be happening?
Here are the relevant parts of the MMSReceiver class that I have made using the two threads mentioned earlier as a guide.
First, is the onReceive method...
public class MMSReceiver extends BroadcastReceiver {
private static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED";
private static final String MMS_DATA_TYPE = "application/vnd.wap.mms-message";
private static String message;
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Test" , "MMSReceiver!");
Uri uri = Uri.parse("content://mms-sms/conversations");
String action = intent.getAction();
String type = intent.getType();
//Log.d("MMS", "action is " + action + " , type is " + type);
final Context cont = context;
ContentResolver cr = context.getContentResolver();
final String[] projection = new String[]{"*"};
Uri MMSuri = Uri.parse("content://mms/inbox/");
Cursor MmsIDquery = cr.query(uri, projection, null, null, null);
MmsIDquery.moveToFirst();
String mid = MmsIDquery.getString(MmsIDquery.getColumnIndex("_id"));
Log.d("MMS", "message id for unreadable message is " + mid);
message = getMessageText(cont, mid);
...
The getMessageText method is passed the context and the message id and is written as this...
/* gets message text */
public String getMessageText(Context context, String mmsid){
Log.d("MMS", "mmsid was " + mmsid);
String message = null;
String mid = ""+(Integer.parseInt(mmsid)+2);
Log.d("MMS", "mmsid is now " + mid);
String selectionPart = "mid=" + mmsid;
Uri mmsTextUri = Uri.parse("content://mms/part");
Cursor cursor = context.getContentResolver().query(mmsTextUri, null, selectionPart, null, null);
if (cursor.moveToFirst()){
do{
String partId = cursor.getString(cursor.getColumnIndex("_id"));
String type = cursor.getString(cursor.getColumnIndex("ct"));
Log.d("MMS", "getMessageText was called, partId = " + partId + " , type = " + type);
if ("text/plain".equals(type)){
String data = cursor.getString(cursor.getColumnIndex("_data"));
Log.d("MMS", "data was " + data);
if (data != null){
message = getMmsText(context, partId);
Log.d("MMS", "body was " + message);
} else {
message = cursor.getString(cursor.getColumnIndex("text"));
Log.d("MMS", "body was " + message);
}
}
} while (cursor.moveToNext());
} else {
Log.d("MMS", "Query returned nothing in getMessageText()");
}
return message;
}
Within this method, the getMmsText is called. I realize that this process is a bit redundant, but I was having a hard time understanding all of what goes on during this process so I kept it as similar to the original threads as I could in order to be sure that the problem wasn't in the way that I reduced it for my own code.
getMmsText looks like this...
public String getMmsText(Context c, String id){
Log.d("MMS", "getMmsText was called with " + id);
Uri partUri = Uri.parse("content://mms/inbox/" + id);
InputStream is = null;
StringBuilder sb = new StringBuilder();
try{
is = c.getContentResolver().openInputStream(partUri);
if (is != null){
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader reader = new BufferedReader(isr);
String temp = reader.readLine();
while(temp != null){
sb.append(temp);
temp = reader.readLine();
}
}
} catch (IOException e){}
finally {
if (is != null){
try{
is.close();
} catch (IOException e){}
}
}
return sb.toString();
}
Thank you so much for your help and please let me know if you have any questions that can help with your answering.
I, myself, have not done the whole process exactly but am currently researching it and this is what I have learned thus far. I recall reading before that listening for android.provider.Telephony.WAP_PUSH_RECEIVED will only notify you of an incoming MMS. My understanding is that the intent is more of a receipt and does not actually mean the MMS is in the phone yet, or more precisely, in the database to pull from. That may explain why you are only getting the second to last. If you want to get the MMS when it's finished and ready to be pulled from the database, I think you'll need a ContentObserver to notify you of database updates.
I have a path like this:
content://media/external/audio/media/7181
That was obtained like this String mSelectedPath = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/";
and then I append the song id to this.
I want to convert it into a path such as /mnt/sdcard/..
How do I do this?
Android's media database stores the path to files in the DATA column. You can read that via
long id = 7181;
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
ContentResolver cr = getContentResolver();
String[] projection = { MediaColumns.DATA };
String selection = null;
String[] selectionArgs = null;
String sortOrder = null;
Cursor c = cr.query(uri, projection, selection, selectionArgs, sortOrder);
String path = null;
if (c != null) {
if (c.moveToFirst()) {
path = c.getString(0);
}
c.close();
}
Log.d("XYZ", "Path of " + id + " is:" + path);
But like #CommonsWare said it's possible that (especially on future android versions) there is no file you can access or even no path at all, meaning the path you get might be worthless.
Luckily ContentProvider allows you to read data with IO streams if the provider has that feature implemented (IIRC this one does). So you could read the data represented by that Uri like in below example.
long id = 7181;
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
ContentResolver cr = getContentResolver();
InputStream is = null;
try {
is = cr.openInputStream(uri);
is.read(); // replace with useful code.
} catch (FileNotFoundException e) {
Log.w("XYZ", e);
} catch (IOException e) {
Log.w("XYZ", e);
} finally {
if (is != null)
try {
is.close();
} catch (IOException e) {
// ignored
}
}
You don't. It is possible that there is no file (e.g., bytes are stored in a BLOB column in a database, the content represents a stream), or the file is in a location that is inaccessible by your process.
I want to read the message body of a new incoming SMS in android, programmatically.
I tried something but that doesn't return any contents:
Uri uri = Uri.parse("content://sms/inbox");
ContextWrapper context = null;
Cursor c = context.getContentResolver().query(uri, null, null ,null,null);
String body = null;
String number=null;
if(c.moveToFirst()) {
body = c.getString(c.getColumnIndexOrThrow("body")).toString();
number = c.getString(c.getColumnIndexOrThrow("address")).toString();
}
c.close();
I have posted some sample programs about this on my class website.
Here is the example Read SMS Example
Here is a snippet of code. Basically your can register a broadcast receiver to listen for SMS_Receive and check out the following.
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("mySMS");
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
SmsMessage sms = SmsMessage.createFromPdu((byte[])pdus[0]);
Log.i("mobile.cs.fsu.edu", "smsActivity : SMS is <" + sms.getMessageBody() +">");
//strip flag
String message = sms.getMessageBody();
while (message.contains("FLAG"))
message = message.replace("FLAG", "");
TextView tx = (TextView) findViewById(R.id.TextBox);
tx.setText(message);
} else
Log.i("mobile.cs.fsu.edu", "smsActivity : NULL SMS bundle");
Below is the piece of code which read the incoming message and display in the list view, don' forget to add the permission in manifest file:
<uses-permission android:name="android.permission.READ_SMS"/>
Here the code:
listitem=(ListView)findViewById(R.id.ListView);
Uri mSmsQueryUri = Uri.parse("content://sms/inbox");
List<String> messages = new ArrayList<String>();
Cursor cursor = null;
try {
cursor = getContentResolver().query(mSmsQueryUri, null, null, null, null);
if (cursor == null) {
Log.i(TAG, "cursor is null. uri: " + mSmsQueryUri);
}
for (boolean hasData = cursor.moveToFirst(); hasData; hasData = cursor.moveToNext()) {
final String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
messages.add(body);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
cursor.close();
}
listitem.setAdapter(new ArrayAdapter<String>(ReadMessage.this, android.R.layout.simple_list_item_1,messages));
A very easy solution would be to use this SMS Parser library:
https://github.com/adorsys/sms-parser-android
compile 'de.adorsys.android:smsparser:0.0.3'
Using it you can either read the whole message, or specific parts of the incoming message. You can also set the phone numbers from which the message will be coming.
If you need more info about how it works or its usage check the github repository I listed above.
Here in this example i'll demonstrate you that how to read the recent received(incoming) sms from inbox and to show it in textview.
fstmsgBtn.setOnClickListener(new OnClickListener()
{ public void onClick(View v)
{
Uri my_uri = Uri.parse("content://sms/inbox");
Cursor readFstSms =v.getContext().getContentResolver().query(my_uri, null, null ,null,null);
if(readFstSms.moveToFirst())
{
String msg_body = c.getString(c.getColumnIndexOrThrow("body")).toString();
//String sender_number = c.getString(c.getColumnIndexOrThrow("address")).toString();
readtxt.setText(msg_body);
}
readFstSms.close();
}
});
listitem=(ListView)findViewById(R.id.list_view);
Uri mSmsQueryUri = Uri.parse("content://sms/inbox");
List<String> messages = new ArrayList<String>();
Cursor cursor = null;
try {
cursor = getContentResolver().query(mSmsQueryUri, null, null, null, null);
if (cursor == null) {
// Log.i(TAG, "cursor is null. uri: " + mSmsQueryUri);
}
for (boolean hasData = cursor.moveToFirst(); hasData; hasData = cursor.moveToNext()) {
final String body = cursor.getString(cursor.getColumnIndexOrThrow("body")).toString();
final String sender_no= cursor.getString(cursor.getColumnIndexOrThrow("address")).toString();
final String date= cursor.getString(cursor.getColumnIndexOrThrow("date"));
final String type =cursor.getString(cursor.getColumnIndexOrThrow("type"));
messages.add(body);
messages.add(sender_no);
messages.add(date);
messages.add(type);
}
} catch (Exception e) {
//Log.e(TAG, e.getMessage());
} finally {
cursor.close();
}
listitem.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,messages));
}
}