|
Replies:
12
-
Last Post:
Jul 16, 2017 3:05 AM
Last Post By: duf _
|
|
|
Posts:
28
Registered:
7/2/06
|
|
I want to read only body of the sms message and my code looks like this:
_di_JCursor cursor;
_di_Jnet_Uri uri;
uri = StrToJURI( "content://sms/inbox" );
cursor = SharedActivity()->getContentResolver()->query( uri, nullptr, nullptr, nullptr, nullptr );
int bodyidx = cursor->getColumnIndex( StringToJString("body") );
String body;
while ( cursor->moveToNext )
{
body = JStringToString( cursor->getString(bodyidx) );
}
Memo1->Lines->Add(body);
There is some old and one new sms in the device and after click button to read sms I got errors:
First chance exception at $61C3F582. Exception class Bus error (10). Process Project1.apk (4600) First chance exception at $61D2B76E. Exception class Segmentation fault (11). Process Project1.apk (4731)
This code is taken from the post written in Delphi from this side:
https://stackoverflow.com/questions/34520148/how-to-code-read-sms-messages-from-android-kitkat-delphi-xe8
And is a little shorter than original to check if this work but I do not why not working. Please give me some directions how to improve this code
|
|
|
Posts:
9,447
Registered:
12/23/01
|
|
duf _ wrote:
cursor = SharedActivity()->getContentResolver()->query( uri,
nullptr, nullptr, nullptr, nullptr );
You are not checking if query() returns a null pointer, which it can.
while ( cursor->moveToNext )
moveToNext() is a method, but you are missing the parenthesis required
to tell the compiler that you want to call the method at runtime:
while ( cursor->moveToNext() )
The parenthesis are optional in Delphi when no input parameters are
being passed in.
There is some old and one new sms in the device
Since your example is only interested in the "body" column, you should
specify that column (and any other columns you are actually interested
in) in the "projection" parameter of ContentResolver::query().
Otherwise, it returns everything, most of which you are ignoring, which
is inefficient, especially on a mobile device.
But, why are you looping over the entire inbox just to find the last
SMS message? Why are you retreiving the body String of all the
previous SMS messages that you are not interested in? Android's Cursor
class has a moveToLast() method:
_di_Jnet_Uri uri = StrToJURI( L"content://sms/inbox" );
_di_JCursor cursor = SharedActivity()->getContentResolver()->query(
uri, nullptr, nullptr, nullptr, nullptr );
if ( cursor )
{
if ( cursor->moveToLast() )
{
int bodyidx = cursor->getColumnIndex( StringToJString(L"body") );
String body = JStringToString( cursor->getString(bodyidx) );
Memo1->Lines->Add(body);
}
}
However, if you are only interested in enumerating unread SMS messages
(which can be more than 1), you should use the "selection" parameter of
query() to restrict the search to just unread messages:
_di_Jnet_Uri uri = StrToJURI( L"content://sms/inbox" );
_di_JCursor cursor = SharedActivity()->getContentResolver()->query(
uri, nullptr, StringToJString(L"read = 0"), nullptr, nullptr );
if ( cursor )
{
int bodyidx = cursor->getColumnIndex( StringToJString(L"body") );
while ( cursor->moveToNext() )
{
String body = JStringToString( cursor->getString(bodyidx) );
Memo1->Lines->Add(body);
}
}
after click button to read sms I got errors:
+First chance exception at $61C3F582. Exception class Bus error (10).
Process Project1.apk (4600) First chance exception at $61D2B76E.
Exception class Segmentation fault (11). Process Project1.apk (4731)+
Segfault(11) is equivilent to an AccessViolation on Windows. You are
trying to access memory you don't have access to.
And is a little shorter than original to check if this work but I do
not why not working.
That is what the debugger is for.
--
Remy Lebeau (TeamB)
|
|
|
|
Posts:
28
Registered:
7/2/06
|
|
duf _ wrote:
cursor = SharedActivity()->getContentResolver()->query( uri,
nullptr, nullptr, nullptr, nullptr );
You are not checking if query() returns a null pointer, which it can.
while ( cursor->moveToNext )
moveToNext() is a method, but you are missing the parenthesis required
to tell the compiler that you want to call the method at runtime:
while ( cursor->moveToNext() )
The parenthesis are optional in Delphi when no input parameters are
being passed in.
There is some old and one new sms in the device
Since your example is only interested in the "body" column, you should
specify that column (and any other columns you are actually interested
in) in the "projection" parameter of ContentResolver::query().
Otherwise, it returns everything, most of which you are ignoring, which
is inefficient, especially on a mobile device.
But, why are you looping over the entire inbox just to find the last
SMS message? Why are you retreiving the body String of all the
previous SMS messages that you are not interested in? Android's Cursor
class has a moveToLast() method:
_di_Jnet_Uri uri = StrToJURI( L"content://sms/inbox" );
_di_JCursor cursor = SharedActivity()->getContentResolver()->query(
uri, nullptr, nullptr, nullptr, nullptr );
if ( cursor )
{
if ( cursor->moveToLast() )
{
int bodyidx = cursor->getColumnIndex( StringToJString(L"body") );
String body = JStringToString( cursor->getString(bodyidx) );
Memo1->Lines->Add(body);
}
}
However, if you are only interested in enumerating unread SMS messages
(which can be more than 1), you should use the "selection" parameter of
query() to restrict the search to just unread messages:
_di_Jnet_Uri uri = StrToJURI( L"content://sms/inbox" );
_di_JCursor cursor = SharedActivity()->getContentResolver()->query(
uri, nullptr, StringToJString(L"read = 0"), nullptr, nullptr );
if ( cursor )
{
int bodyidx = cursor->getColumnIndex( StringToJString(L"body") );
while ( cursor->moveToNext() )
{
String body = JStringToString( cursor->getString(bodyidx) );
Memo1->Lines->Add(body);
}
}
after click button to read sms I got errors:
+First chance exception at $61C3F582. Exception class Bus error (10).
Process Project1.apk (4600) First chance exception at $61D2B76E.
Exception class Segmentation fault (11). Process Project1.apk (4731)+
Segfault(11) is equivilent to an AccessViolation on Windows. You are
trying to access memory you don't have access to.
And is a little shorter than original to check if this work but I do
not why not working.
That is what the debugger is for.
--
Remy Lebeau (TeamB)
Thank You Remy,
However, if you are only interested in enumerating unread SMS messages
(which can be more than 1), you should use the "selection" parameter of
query() to restrict the search to just unread messages:
But how to mark unread sms as read? I cannot delete read sms probably that my program is not default for sma or there is problem with "delete" sentence
SharedActivity()->getContentResolver()->delete( uri, StringToJString("_ID=" + smsid) );
As "delete" is a special sentence compilation.
Is it possible to set flag read =0 to read=1?
|
|
|
|
Posts:
9,447
Registered:
12/23/01
|
|
|
|
|
Posts:
28
Registered:
7/2/06
|
|
Thank You Remy,
_di_JContentResolver cr = SharedActivity()->getContentResolver();
_di_JCursor cursor = cr->query(...);
if (cursor)
{
int msgididx = cursor->getColumnIndex( StringToJString(L"_id") );
...
while (cursor->moveToNext())
{
String smsid = JStringToString(cursor->getString(msgididx));
...
_di_JContentValues values = new TJContentValues();
values->put(L"read", TJBoolean::JavaClass->valueOf(true));
cr->update(uri, values, StringToJString(L"_id=" + smsid),
nullptr);
}
}
There is a problem with this instruction:
_di_JContentValues values = new TJContentValues();
+[bccaarm Error] Unit1.cpp(87): no viable conversion from 'Androidapi::Jni::Graphicscontentviewtext::TJContentValues *' to '_di_JContentValues' (aka 'DelphiInterface<Androidapi::Jni::Graphicscontentviewtext::JContentValues>')
systobj.h(261): candidate constructor not viable: no known conversion from 'Androidapi::Jni::Graphicscontentviewtext::TJContentValues *' to 'const DelphiInterface<Androidapi::Jni::Graphicscontentviewtext::JContentValues> &' for 1st argument
systobj.h(268): candidate constructor not viable: no known conversion from 'Androidapi::Jni::Graphicscontentviewtext::TJContentValues *' to 'Androidapi::Jni::Graphicscontentviewtext::JContentValues *' for 1st argument
systobj.h(254): candidate template ignored: could not match 'DelphiInterface<type-parameter-0-0>' against 'Androidapi::Jni::Graphicscontentviewtext::TJContentValues *'
systobj.h(278): candidate template ignored: disabled by 'enable_if' [with TArg = Androidapi::Jni::Graphicscontentviewtext::TJContentValues *]+
'delete' is a reserved keyword in C++. If you look in the
Androidapi.JNI.GraphicsContentViewText.hpp header file, you will see
that the delete() method is declared with a capital 'D':
SharedActivity()->getContentResolver()->Delete( uri,
StringToJString("_ID=" + smsid) );
And "Delete" method needs 3 arguments and when I used "nullptr+ there is exception during program is running
SharedActivity()->getContentResolver()->Delete( uri, StringToJString("_ID=" + smsid), nullptr );
First chance exception at $61E241D1. Exception class EJNIException with message 'java.lang.IllegalArgumentException: Unknown URL'. Process Project1.apk (28562)
|
|
|
|
Posts:
9,447
Registered:
12/23/01
|
|
duf _ wrote:
There is a problem with this instruction:
_di_JContentValues values = new TJContentValues();
Try this instead:
_di_JContentValues values = TJContentValues::JavaClass->init(1);
And "Delete" method needs 3 arguments and when I used "nullptr+ there
is exception during program is running
SharedActivity()->getContentResolver()->Delete( uri,</div>
StringToJString("_ID=" + smsid), nullptr );
<div class="jive-quote">
+First chance exception at $61E241D1. Exception class EJNIException
with message 'java.lang.IllegalArgumentException: Unknown URL'.
That has nothing to do with passing nullptr in the 3rd parameter. That
parameter is allowed to be null. That parameter is just for passing an
array of argument values when the 2nd parameter is a string containing
'?' wildcards in it. Same as the corresponding parameters in query().
Read the error message more carefully, it is complaining about the URL
specified in the 1st parameter. That means you are not specifying the
correct URL to perform the deletion with. "content://sms/inbox" as the
URL should work just fine for query(), update(), and delete(). But I
have seen some examples use "content://sms" instead.
And if that doesn't work, I have seen reports say that the 3rd
parameter of delete() may be required, so try something like this:
TJavaObjectArray__1<_di_JString> *arg = new
TJavaObjectArray__1<_di_JString>(1);
arg->Items[0] = smsid;
SharedActivity()->getContentResolver()->Delete( uri,
StringToJString("_ID=?"), arg );
--
Remy Lebeau (TeamB)
|
|
|
|
Posts:
28
Registered:
7/2/06
|
|
duf _ wrote:
There is a problem with this instruction:
_di_JContentValues values = new TJContentValues();
Try this instead:
_di_JContentValues values = TJContentValues::JavaClass->init(1);
And "Delete" method needs 3 arguments and when I used "nullptr+ there
is exception during program is running
SharedActivity()->getContentResolver()->Delete( uri,</div>
StringToJString("_ID=" + smsid), nullptr );
<div class="jive-quote">
+First chance exception at $61E241D1. Exception class EJNIException
with message 'java.lang.IllegalArgumentException: Unknown URL'.
That has nothing to do with passing nullptr in the 3rd parameter. That
parameter is allowed to be null. That parameter is just for passing an
array of argument values when the 2nd parameter is a string containing
'?' wildcards in it. Same as the corresponding parameters in query().
Read the error message more carefully, it is complaining about the URL
specified in the 1st parameter. That means you are not specifying the
correct URL to perform the deletion with. "content://sms/inbox" as the
URL should work just fine for query(), update(), and delete(). But I
have seen some examples use "content://sms" instead.
And if that doesn't work, I have seen reports say that the 3rd
parameter of delete() may be required, so try something like this:
TJavaObjectArray__1<_di_JString> *arg = new
TJavaObjectArray__1<_di_JString>(1);
arg->Items[0] = smsid;
SharedActivity()->getContentResolver()->Delete( uri,
StringToJString("_ID=?"), arg );
--
Remy Lebeau (TeamB)
Thank You Remy,
For the first argument in the case "content://sms/inbox" still the same error during using program
TJavaObjectArray__1<_di_JString> *arg = new TJavaObjectArray__1<_di_JString>(1);
arg->Items[0] = StringToJString(smsid);
SharedActivity()->getContentResolver()->Delete( uri, StringToJString("_ID=" + smsid), arg );
First chance exception at $61D48BA1. Exception class EJNIException with message 'java.lang.IllegalArgumentException: Unknown URL'. Process Project1.apk (29480)
Try this instead:
_di_JContentValues values = TJContentValues::JavaClass->init(1);
In this case there is problem with member "put"
_di_JContentValues values = TJContentValues::JavaClass->init(1);
values->put( L"read", TJBoolean::JavaClass->valueOf(true) );
cr->update( uri, values, StringToJString(L"_id=" + smsid), nullptr );
[bccaarm Error] Unit1.cpp(91): no matching member function for call to 'put'
|
|
|
|
Posts:
9,447
Registered:
12/23/01
|
|
duf _ wrote:
For the first argument in the case "content://sms/inbox" still the
same error during using program
Did you try "content://sms" yet?
In this case there is problem with member "put"
_di_JContentValues values = TJContentValues::JavaClass->init(1);
values->put( L"read", TJBoolean::JavaClass->valueOf(true) );
cr->update( uri, values, StringToJString(L"_id=" + smsid), nullptr
);
+[bccaarm Error] Unit1.cpp(91): no matching member function for call
to 'put'+
Like everything else in Android JNI, use StringToJString() when passing
in String values:
values->put( StringToJString(L"read"),
TJBoolean::JavaClass->valueOf(true) );
--
Remy Lebeau (TeamB)
|
|
|
|
Posts:
28
Registered:
7/2/06
|
|
duf _ wrote:
For the first argument in the case "content://sms/inbox" still the
same error during using program
Did you try "content://sms" yet?
In this case there is problem with member "put"
_di_JContentValues values = TJContentValues::JavaClass->init(1);
values->put( L"read", TJBoolean::JavaClass->valueOf(true) );
cr->update( uri, values, StringToJString(L"_id=" + smsid), nullptr
);
+[bccaarm Error] Unit1.cpp(91): no matching member function for call
to 'put'+
Like everything else in Android JNI, use StringToJString() when passing
in String values:
values->put( StringToJString(L"read"),
TJBoolean::JavaClass->valueOf(true) );
--
Remy Lebeau (TeamB)
Hi Remy,
Thank You for reply
Did you try "content://sms" yet?
Yes, and there is answer from machine:
First chance exception at $61D48BA1. Exception class EJNIException with message 'java.lang.IllegalArgumentException: Too many bind arguments. 1 arguments were provided but the statement needs 0 arguments.'. Process Project1.apk (30349)
And this example is ideal, it change unread to read status
_di_JContentValues values = TJContentValues::JavaClass->init(1);
values->put( StringToJString(L"read"),TJBoolean::JavaClass->valueOf(true) );
cr->update( uri, values, StringToJString(L"_id=" + smsid), nullptr );
|
|
|
|
Posts:
9,447
Registered:
12/23/01
|
|
duf _ wrote:
Yes, and there is answer from machine:
+First chance exception at $61D48BA1. Exception class EJNIException
with message 'java.lang.IllegalArgumentException: Too many bind
arguments. 1 arguments were provided but the statement needs 0
arguments.'. Process Project1.apk (30349)+
Was that on the call to delete()? Did you change the value of the 2nd
parameter from StringToJString(L"_ID=" + smsid) to
StringToJString("_ID=?"), like I showed you?
--
Remy Lebeau (TeamB)
|
|
|
|
Posts:
28
Registered:
7/2/06
|
|
Did you change the value of the 2nd
parameter from StringToJString(L"_ID=" + smsid) to
StringToJString("_ID=?"), like I showed you?
No
This change and "content://sms" is all right and works perfect 
I tried it on Android v.4.4.4
Thanks for Your patient
|
|
|
|
Posts:
7,731
Registered:
9/22/99
|
|
duf _ wrote:
Thanks for Your patient
Hey, I am the one with patients. He is the one with patience. <g>
--
Rudy Velthuis http://www.rvelthuis.de
"You exist only in what you do."
-- Federico Fellini
|
|
|
|
Posts:
28
Registered:
7/2/06
|
|
Did you try "content://sms" yet?
--
Remy Lebeau (TeamB)
But in this case how to distinguish between inbox and outbox? How I got to know send messages have not status read or not read so if I try to set cursor to the last message (I think about this send) and set status to read the condition is not fulfilled
cursor = SharedActivity()->getContentResolver()->query( uri, nullptr, StringToJString(L"read = 0"), nullptr, nullptr ); // "read = 0" <-- send message
if ( cursor->moveToLast() ) // last send message
{
... // this is not fulfilled
}
But if I try to use "content://sms/outbox" there is always no condition
if ( cursor->moveToLast() )
|
|
|
|
Legend
|
|
Helpful Answer
(5 pts)
|
|
Correct Answer
(10 pts)
|
|
Connect with Us