I am developing a system application in which I have to send a message from device programmatically and delete the message after sending.Everything working properly except below point
If the message sent successfully then I am able to find it from SMS content URI but if the message failures then I am not getting it from Content URI.I am using below code for deleting message
public void deleteTheMessage(Context context, String value) {
Uri uri = Uri.parse("content://sms");
Cursor c = context.getApplicationContext().getContentResolver().query(uri, null, null, null, null);
try {
if (c != null) {
Log.i("deleteTheMessage-->", " count : " + c.getCount());
} else {
Log.i("deleteTheMessage-->", " c null: ");
}
while (c.moveToNext()) {
try {
if (c != null && c.moveToFirst()) {
do {
String address = c.getString(2);
String id = c.getString(0);
long threadId = c.getLong(1);
Log.i("deleteTheMessage-->", " address: " + address + " body: " + "" + " threadId: " + threadId + " id: " + id);
try {
if (address.contains(value)) {
int deltedrowcount = context.getApplicationContext().getContentResolver().delete(uri, "thread_id = " + threadId, null);
if (deltedrowcount != 0) {
Log.i("deleteTheMessage-->", " SMS has Deleted successfully " + deltedrowcount);
}
Log.i("deleteTheMessage-->", " body " + address);
}
} catch (Exception e) {
Log.i("deleteTheMessage-->", "SmsWriteOpUtil Exception in deleting SMS " + e.getMessage());
}
} while (c.moveToNext());
}
} catch (Exception e) {
Log.i("deleteTheMessage-->", "c.moveToNext() Exception in deleting SMS" + e.getMessage());
}
}
} catch (Exception e) {
Log.i("deleteTheMessage-->", " try Exception in deleting SMS: " + e.getMessage());
} finally {
c.close();
}
}
I want to delete message address by 11345 Please see below screenshot.
Finally, I got the solution to delete the undelivered message using below code.
long threadId = Telephony.Threads.getOrCreateThreadId(context, phoneNumber);
LogMgr.i("deleteByThreadID-->" + " threadId : " + threadId);
int threadIdDeletedCount = context.getContentResolver().delete(Uri.parse("content://sms"), "thread_id =?", new String[]{String.valueOf(threadId)});
LogMgr.i("deleteByThreadID: --> threadIdDeletedCount " + threadIdDeletedCount);
phoneNumber this the number on which message was sent.
Related
Trying to delete the sent sms from app, when I have tried below code in Lenovo A6000(5.0.2) device
public static void deleteMessage(Context context, String phoneNo, String message) {
try {
Log.d(TAG, "deleteMessage: Deleting SMS from inbox");
Uri uriSms = Uri.parse("content://sms/");
Cursor c = context.getContentResolver().query(uriSms,
new String[]{"_id", "thread_id", "address",
"person", "date", "body"}, null, null, null);
Uri uri = null;
if (c != null && c.moveToFirst()) {
do {
long id = c.getLong(0);
long threadId = c.getLong(1);
String address = c.getString(2);
String body = c.getString(5);
int rowsDeleted = 0;
Log.d(TAG, "Deleting threads: " + threadId);
Log.d(TAG, "deleteMessage: id- "+ id + "" +
" threadId- " + threadId + "" +
" body- " + body + "" +
" rowsDeleted- " + rowsDeleted + "" +
" address- " + address);
if (address.equalsIgnoreCase(phoneNo)
&& body.equalsIgnoreCase(message)) {
ConversationQueryHandler handler = new ConversationQueryHandler(context.getContentResolver(), context);
synchronized (sDeletingThreadsLock) {
Log.v(TAG, "Conversation startDelete sDeletingThreads: " + sDeletingThreads);
if (sDeletingThreads) {
Log.e(TAG, "startDeleteAll already in the middle of a delete", new Exception());
}
sDeletingThreads = true;
uri = ContentUris.withAppendedId(Telephony.Threads.CONTENT_URI, threadId);
String selection = true ? null : "locked=0";
handler.setDeleteToken(0);
handler.startDelete(0, new Long(threadId), uri, selection, null);
}
}
} while (c.moveToNext());
}
} catch (Exception e) {
Log.d(TAG, "deleteMessage: Could not delete SMS from inbox: " + e.getMessage());
}
}
The ConversationQueryHandler sends 1 as a result in case of successful deletion of sms on to onDeletionComplete but this doesn't work in all the devices.
private static Object sDeletingThreadsLock = new Object();
private static boolean sDeletingThreads;
public static class ConversationQueryHandler extends AsyncQueryHandler {
private int mDeleteToken;
private Context mContext;
public ConversationQueryHandler(ContentResolver cr, Context context) {
super(cr);
mContext = context;
}
public void setDeleteToken(int token) {
mDeleteToken = token;
}
/**
* Always call this super method from your overridden onDeleteComplete function.
*/
#Override
protected void onDeleteComplete(int token, Object cookie, int result) {
Log.v(TAG, "Conversation onDeleteComplete token: " + token + " cookie- " + cookie + " result- " + result);
if (token == mDeleteToken) {
// release lock
synchronized (sDeletingThreadsLock) {
sDeletingThreads = false;
sDeletingThreadsLock.notifyAll();
}
}
}
}
I have tested this and found it is failed to delete the sms in all the below devices
Sony Xperia Z1(5.1.1)
Lenovo A200 device (5.1)
Samsung J210F (6.0.1)
As I mentioned earlier I am able to delete sms with the same code in
Lenovo A6000(5.0.2)
Is there a chance I am missing something here, or is this a right way of deleting the sent sms. Thank you for the help in advance.
after I update an object in my syncAdapter I can't get it back by id again. It seems that the id get lost after the update. What leaves behind is a null object.
Here's my source code how I update the object:
#Override
public void updateUserThread(Context ctxt, UserThread userThread, boolean notified)
{
try
{
ContentValues values = new ContentValues();
values.put(DBHandler.TOPIC, userThread.getTopic());
if(userThread.getCreationDate() != null)
values.put(DBHandler.USER_THREAD_CREATION_DATE, userThread.getCreationDate().getTime());
values.put(DBHandler.THREAD_TYPE, Helper.threadTypeToString(userThread.getThreadType()));
values.put(DBHandler.MEETING_PLACE, userThread.getMeetingPlace());
values.put(DBHandler.SUBJECT, userThread.getSubject());
values.put(DBHandler.SENT, Helper.convertBooleanToInt(userThread.isSent()));
if(userThread.getStartDate() != null)
values.put(DBHandler.START_DATE, userThread.getStartDate().getTime()); //Helper.getDateTime(
values.put(DBHandler.FOR_ALL, userThread.isForAll());
values.put(DBHandler.ID_SERVER, userThread.getIdServer());
if(userThread.getAuthor() != null)
values.put(DBHandler.ID_USER_FK, userThread.getAuthor().getIdUser());
if(notified)
{
ctxt.getContentResolver().update(TeamChannelProvider.USER_THREAD_URI, values, DBHandler.ID_USER_THREAD + "=" + "?", new String[]{String.valueOf(userThread.getIdUserThread())});
}
else
{
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
long status = db.update(TABLE_USER_THREAD, values, DBHandler.ID_USER_THREAD + "=?", new String[]{String.valueOf(userThread.getIdUserThread())});
db.setTransactionSuccessful();
db.endTransaction();
Log.i(Constants.TAG, "Status: " + status);
}
}
catch(Exception exc)
{
Log.e(Constants.TAG, "ERROR - DBHandlerTeamChannel -> updateUserThread", exc);
}
finally
{
Log.i(Constants.TAG, "UserThread updated with ID " + (notified ? "(notified) " : "not notified ") + userThread.getIdUserThread() + ", Server-ID: " + userThread.getIdServer());
}
}
db=helper.getReadableDatabase();
cursor=db.query(DBHelper.TABLE, new String[]{DBHelper.CONTACT_NO}, null, null, null, null, null);
String listContact[]=fromCursorToStringArray(cursor);
Log.d("Array",Arrays.toString(listContact));
String sms = "This is custom message" + "\n" + "IMEI : " + mngr.getDeviceId() + "\n" + "Location : " + provider + "\n" + Arrays.toString(listContact) + contact_name;
try
{
android.telephony.SmsManager smsmanager = android.telephony.SmsManager.getDefault();
for(int i=0; i<listContact.length; i++)
{
smsmanager.sendTextMessage(listContact[i], null, sms, null, null);
Log.d("index", listContact[i]);
}
Toast.makeText(getApplicationContext(), "SMS Sent!",Toast.LENGTH_LONG).show();
}
catch (Exception e)
{
Toast.makeText(getApplicationContext(),"SMS faild, please try again later!",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
When I seen in Log it is give me all contact number in array but while I am concat in string at that time contact number does not display in message
String sms = "This is custom message" + "\n" + "IMEI : " + mngr.getDeviceId() + "\n" + "Location : " + provider + "\n" + Arrays.toString(listContact) + contact_name;
Its because of the brackets.
I have created function for remove brackets will work. Its working my side
private String subString(String sms)
{
String temp = "";
for(int i=1;i<(sms.length()-1);i++)
{
temp += sms.charAt(i);
}
return temp;
}
First you put your array to String Variable then after Concat with your message.
String temp=Arrays.toString(listContact);
String sms = "This is custom message" + "\n" + "IMEI : " + mngr.getDeviceId() + "\n" + "Location : " + provider + "\n" + temp + contact_name;
Some times Android cant directly Convert and concat operation simontenously.
Try it hope it will help you.
or
Second thing is check your Contactlist cherecter length becouse there are charecter limit in message. so if contactlist length exceed max allowed length it became media so check this scenario also.
this is quite odd to me: in my project (which by the way is derived from Yaxim, so it's a chat app for android), I'm trying to implement writing notification through the messageeventlistener. I do receive the notification event. To make it appear in the listview (which is in another class) I'm adding a row in the database, as if it were a message (only the text is "..."). I've added a counter and the row is properly inserted in the db (subsequently the row is deleted from the db when the actual message comes). The notifychanges is also called properly. The strange thing is that despite all of this the row doesn't appear in the listview. If I move the procedure a few lines below, on the packetlistener for the regular messages, it gets inserted. However I cannot leave it like that because the packetlistener doesn't receive properly all composing notifications, so it doesn't work all the time for that purpose. Also, while the writing notification is properly inserted into the db, if I keep the procedure in the messageEventNotificationListener() the writing notification message does not get deleted when the actual message arrives (and the iCount keeps increasing); if I put the procedure in the packetListener it does (hence iCount equals 0 after the message is pushed into the db)
This is the messageeventlistener:
private void messageEventNotificationListener(){
// Create a MessageEventManager
if (mMessageEventManager == null)
mMessageEventManager = new MessageEventManager(mXMPPConnection);
// Add the listener that will react to the event notifications
mMessageEventManager.addMessageEventNotificationListener(new MessageEventNotificationListener() {
public void deliveredNotification(String from, String packetID) {
Log.d(TAG, "The message has been delivered (" + from + ", " + packetID + ")");
}
public void displayedNotification(String from, String packetID) {
Log.d(TAG, "The message has been displayed (" + from + ", " + packetID + ")");
}
public void composingNotification(String from, String packetID) {
Log.d(TAG, "The message's receiver is composing a reply (" + from + ", " + packetID + ")");
//controlla se l'utente non sta giĆ scrivendo
String selection = ChatConstants.JID + " = '" + from + "' AND " +
ChatConstants.DELIVERY_STATUS + " = " + ChatConstants.DS_WRITING;
Cursor cursor = mContentResolver.query(ChatProvider.CONTENT_URI,
new String[] { "count(" + ChatConstants._ID + ")" },
selection, null, null);
cursor.moveToFirst();
int iCount = cursor.getInt(0);
//if (iCount == 0)
//{
addChatMessageToDB(ChatConstants.INCOMING, from, "...", ChatConstants.DS_WRITING, System.currentTimeMillis(), packetID);
//}
}
public void offlineNotification(String from, String packetID) {
Log.d(TAG, "The message's receiver is offline (" + from + ", " + packetID + ")");
}
public void cancelledNotification(String from, String packetID) {
Log.d(TAG, "The message's receiver cancelled composing a reply (" + from + ", " + packetID + ")");
}
});
}
and here is the packetlistener:
private void registerMessageListener() {
// do not register multiple packet listeners
if (mPacketListener != null)
mXMPPConnection.removePacketListener(mPacketListener);
PacketTypeFilter filter = new PacketTypeFilter(Message.class);
mPacketListener = new PacketListener() {
public void processPacket(Packet packet) {
try {
if (packet instanceof Message) {
Message msg = (Message) packet;
String chatMessage = msg.getBody();
DeliveryReceipt dr = (DeliveryReceipt)msg.getExtension("received", DeliveryReceipt.NAMESPACE);
if (dr != null) {
Log.d(TAG, "got delivery receipt for " + dr.getId());
changeMessageDeliveryStatus(dr.getId(), ChatConstants.DS_DELIVERED);
}
if (chatMessage == null)
return;
if (msg.getType() == Message.Type.error) {
chatMessage = "<Error> " + chatMessage;
}
long ts;
DelayInfo timestamp = (DelayInfo)msg.getExtension("delay", "urn:xmpp:delay");
if (timestamp == null)
timestamp = (DelayInfo)msg.getExtension("x", "jabber:x:delay");
if (timestamp != null)
ts = timestamp.getStamp().getTime();
else
ts = System.currentTimeMillis();
String fromJID = getJabberID(msg.getFrom());
//elimina il messaggio "writing" se esiste
deleteWritingChatMessageFromDB(fromJID);
if (msg.getExtension("request", DeliveryReceipt.NAMESPACE) != null) {
// got XEP-0184 request, send receipt
sendReceipt(msg.getFrom(), msg.getPacketID());
}
addChatMessageToDB(ChatConstants.INCOMING, fromJID, chatMessage, ChatConstants.DS_NEW, ts, msg.getPacketID());
mServiceCallBack.newMessage(fromJID, chatMessage);
}
}
} catch (Exception e) {
// SMACK silently discards exceptions dropped from processPacket :(
Log.e(TAG, "failed to process packet:");
e.printStackTrace();
}
};
mXMPPConnection.addPacketListener(mPacketListener, filter);
}
and finally the insert and delete method
private void addChatMessageToDB(int direction, String JID,
String message, int delivery_status, long ts, String packetID) {
ContentValues values = new ContentValues();
values.put(ChatConstants.DIRECTION, direction);
values.put(ChatConstants.JID, JID);
values.put(ChatConstants.MESSAGE, message);
values.put(ChatConstants.DELIVERY_STATUS, delivery_status);
values.put(ChatConstants.DATE, ts);
values.put(ChatConstants.PACKET_ID, packetID);
Uri noteUri = mContentResolver.insert(ChatProvider.CONTENT_URI, values);
//mContentResolver.notifyChange(noteUri, null);
}
private void deleteWritingChatMessageFromDB(String JID) {
int count = mContentResolver.delete(ChatProvider.CONTENT_URI,
ChatConstants.JID + " = ? AND " + ChatConstants.MESSAGE + " = ? AND " + ChatConstants.DELIVERY_STATUS + " = ?", new String[] { JID, "...", "3" });
debugLog("deleteWritingChatMessageEntryFromDB: Deleted " + count + " entries");
}
both these methods get called into the ChatProvider class and end with
getContext().getContentResolver().notifyChange(url, null);
Turns out the problem was different: I posting this just in case someone else runs in the same issue. The message was infact inserted into the db, but while the packetlistener returns only the jid, the messageeventlistener returns the jid with the resource at the end as well, which needed to be taken away before the insert. Done that, the message appeared in the list. Also: the code I posted is not completely correct to handle the messageEvent. The listeners need to be called from inside the packetListener directly.
I am currently working on an app that runs an AsyncTask in the background and updates the UI with a progressbar. The progress bar works fine when the app is running, however, when the user exits the app and re-enters, the AsyncTask is still running in the background, but the progress bar won't update. It's as if the AsyncTask has detached itself from the activity. Does anyone have any ideas what might be causing this such as general rules involved with AsyncTasks. I can provide code if needed, but it is rather lengthy, so just let me know what parts you would need to see. I should also note that the AsyncTask does complete, I can tell this because it uploads a database to the server when it finishes.
Here is the code:
public class BackgroundAsyncTask extends AsyncTask {
int myProgress;
#Override
protected void onPostExecute(Void result) {
((TextView) findViewById(R.id.tv1)).setText("");
Cursor cur = sql3.query("videohashes", null, null, null, null,
null, null);
cur.moveToFirst();
while (!cur.isAfterLast()) {
Cursor curFrame = sql3.query("table_" + cur.getString(2), null,
null, null, null, null, null);
curFrame.moveToFirst();
((TextView) findViewById(R.id.tv1)).append("\nPath: "
+ cur.getString(1) + "\nHash: " + cur.getString(2)
+ "\nDate:" + cur.getString(3) + "\nSize: "
+ cur.getString(4) + " bytes\nResolution"
+ cur.getString(5) + "\nFormat: " + cur.getString(6)
+ "\nCodec: " + cur.getString(7) + "\nFPS: "
+ cur.getString(8) + "\n\nFirst Frame Info:\nType: "
+ curFrame.getString(1) + "\ncp_num: "
+ curFrame.getString(2) + "\ndp_num: "
+ curFrame.getString(3) + "\npts: "
+ curFrame.getString(4) + "\nqstride: "
+ curFrame.getString(5) + "\nsize: "
+ curFrame.getString(6) + "\nqp_stddev: "
+ curFrame.getString(7) + "\ncount: "
+ curFrame.getString(8) + "\nqp_avg: "
+ curFrame.getString(9) + "\n\n");
cur.moveToNext();
}
cur.close();
((Button) findViewById(R.id.btnSend)).setEnabled(true);
((Button) findViewById(R.id.btnStart)).setEnabled(true);
sql3.close();
sharedPreferences.edit().putString("lastVideoInfo", ((TextView) findViewById(R.id.tv1)).getText().toString()).commit();
sharedPreferences.edit().putBoolean("asyncTaskRunning", false).commit();
dateNow = new Date();
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
totProgress = 0;
currVid = 0;
curProgress = 0;
}
#Override
protected void onProgressUpdate(Integer... values) {
progress.setProgress(values[0]);
}
#Override
protected Void doInBackground(Void... arg0) {
// Calculate total size of all files
for (String path : myFiles) {
totProgress += getFileSize(path);
}
progress.setMax(totProgress);
String strDB3File = getFilesDir().getPath() + "/VideoHashes.db3";
sql3 = SQLiteDatabase.openDatabase(strDB3File, null,
SQLiteDatabase.CREATE_IF_NECESSARY);
try {
String mysql = "CREATE TABLE IF NOT EXISTS videohashes (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, path TEXT NOT NULL, hash TEXT NOT NULL, date TEXT NOT NULL, size INTEGER, resolution TEXT NOT NULL, codec TEXT NOT NULL, format TEXT NOT NULL, fps TEXT NOT NULL)";
sql3.execSQL(mysql);
} catch (SQLiteException e) {
// TODO: handle exception
}
for (String path : myFiles) {
try {
String hash = getMD5Checksum(path);
Cursor curFrame = sql3.query("videohashes",
new String[] { "hash" }, "hash=?",
new String[] { hash }, null, null, null);
if (!curFrame.moveToFirst()) {
ContentValues myInsertData = new ContentValues();
myInsertData.put("path", path);
myInsertData.put("hash", hash);
Date date = new Date();
myInsertData.put("date", dateFormat.format(date));
myInsertData.put("size", getFileSize(path));
naInit(path);
Log.i("VPMA", "After naInit");
int[] prVideoRes = naGetVideoResolution();
myInsertData.put("resolution", prVideoRes[0] + "x"
+ prVideoRes[1]);
String prVideoCodecName = naGetVideoCodecName();
myInsertData.put("codec", prVideoCodecName);
String prVideoFormatName = naGetVideoFormatName();
myInsertData.put("format", prVideoFormatName);
double prFps = naGetVideoFPS();
Log.i("VPMA", "fps: " + prFps);
myInsertData.put("fps", prFps);
Object[] prObjArray = naGetArray();
Log.i("VPMA", (String) prObjArray[0]);
String[] prStrArray = Arrays.copyOf(prObjArray,
prObjArray.length, String[].class);
Log.i("VPMA", "before frames");
try {
String mysql = "CREATE TABLE table_"
+ hash
+ " (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, cp_num TEXT NOT NULL, dp_num TEXT NOT NULL, pts TEXT NOT NULL, qstride TEXT NOT NULL, size TEXT NOT NULL, qp_stddev TEXT NOT NULL, count TEXT NOT NULL, qp_avg TEXT NOT NULL)";
sql3.execSQL(mysql);
} catch (SQLiteException e) {
// TODO: handle exception
}
for (String str : prStrArray) {
ContentValues myFrameInsertData = new ContentValues();
String[] strArr = str.split(",");
if (strArr.length == 9) {
String stddev = "", strCount = "", strQp_avg = "";
double sd, qp_avg, count = 0, sum = 0, sqrSum = 0;
try {
count = Integer.parseInt(strArr[6].trim());
sum = Integer.parseInt(strArr[7].trim());
sqrSum = Integer.parseInt(strArr[8].trim());
//sd = (sum * sum / count);
sd = (sqrSum - (sum*sum/count))/(count-1);//(sqrSum - sd) / (count - 1);
stddev = String.valueOf(sd);
qp_avg = sum / count;
strCount = String.valueOf(count);
strQp_avg = String.valueOf(qp_avg);
} catch (Exception e) {
Log.i("Error: ", "error converting values");
}
//Log.i("Java Code: ", "Sum: " + sum + " SqrSum: " + sqrSum + " Count: " + count);
//Log.i("Java Code: ", "StdDev: " + stddev + " qp_avg: " + strQp_avg);
myFrameInsertData.put("type", strArr[0]);
myFrameInsertData.put("cp_num", strArr[1]);
myFrameInsertData.put("dp_num", strArr[2]);
myFrameInsertData.put("pts", strArr[3]);
myFrameInsertData.put("qstride", strArr[4]);
myFrameInsertData.put("size", strArr[5]);
myFrameInsertData.put("qp_stddev", stddev);
myFrameInsertData.put("count", strCount);
myFrameInsertData.put("qp_avg", strQp_avg);
sql3.insert("table_" + hash, null,
myFrameInsertData);
}
}
sql3.insert("videohashes", null, myInsertData);
naClose();
}
curFrame.close();
currVid++;
curProgress += getFileSize(path);
publishProgress(curProgress);
Log.i("Progress", "CurrVid:" + currVid + " Max:"
+ progress.getMax());
} catch (Exception e) {
Log.i("File", "File not Found");
}
}
return null;
}
}
}
if (sharedPreferences.getBoolean("asyncTaskRunning", false) == false)
{
((Button) findViewById(R.id.btnStart)).setEnabled(false);
progress = (ProgressBar) findViewById(R.id.progressBar1);
text = (TextView) findViewById(R.id.tv1);
if (sharedPreferences.contains("lastVideoInfo"))
{
text.setText("Last Video Information Parsed " + "(" + dateFormat.format(dateNow) + "):\n\n" + sharedPreferences.getString("lastVideoInfo", ""));
((Button) findViewById(R.id.btnSend)).setEnabled(true);
}
else
{
text.setText("");
((Button) findViewById(R.id.btnSend)).setEnabled(false);
}
progress.setProgress(0);
myFiles = new ArrayList<String>();
new StartAsyncTask().execute();
}
}
When the Activity is destroyed, it loses its reference to the AsyncTask, as when the AsyncTask is created it is passed in a reference to the instance of the Activity that creates it. When the instance dies, the reference to the Activity becomes useless.
A better approach would be put the AsyncTask into a Service, set up the Service and set the AsyncTask running in the Service and bind your Activity to the Service.
Then when a new instance of the Activity is created (ie when the user re-enters the app), it can bind to the same Service instance that's already running and pass in a reference to its self to receive progress info.
Another advantage of this approach is that your Service can put a notification icon in the notification bar, which greatly reduces it chances of being killed by the system, the user could view progress at a glance, and even be notified of when the process is complete.
Allowing an AsyncTask to be cut loose from its owner (is the Activity) and trusting that it will complete what its doing is a pretty bad idea, and will probably have some unexpected results, lead to potential memory leaks etc.