Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: How to read SMS with C++ Builder in Android



Permlink Replies: 12 - Last Post: Jul 16, 2017 3:05 AM Last Post By: duf _
duf _

Posts: 28
Registered: 7/2/06
How to read SMS with C++ Builder in Android
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 10, 2017 1:59 AM
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
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 10, 2017 11:38 AM   in response to: duf _ in response to: duf _
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)
duf _

Posts: 28
Registered: 7/2/06
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 10, 2017 3:20 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
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?
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 11, 2017 12:43 PM   in response to: duf _ in response to: duf _
duf _ wrote:

But how to mark unread sms as read?

Use the ContentResolver::update() method:

https://developer.android.com/reference/android/content/ContentResolver.html#update%28android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String%5B%5D%29

https://developer.android.com/guide/topics/providers/content-provider-basics.html#Updating

For example:

_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);
    }
}


I cannot delete read sms probably that my program is not default for
sma or there is problem with "delete" sentence

'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) );


Is it possible to set flag read =0 to read=1?

Yes. See further above.

--
Remy Lebeau (TeamB)
duf _

Posts: 28
Registered: 7/2/06
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 11, 2017 4:30 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
duf _ wrote:

But how to mark unread sms as read?

Use the ContentResolver::update() method:

https://developer.android.com/reference/android/content/ContentResolver.html#update%28android.net.Uri,%20android.content.ContentValues,%20java.lang.String,%20java.lang.String%5B%5D%29

https://developer.android.com/guide/topics/providers/content-provider-basics.html#Updating

For example:

_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);
    }
}


I cannot delete read sms probably that my program is not default for
sma or there is problem with "delete" sentence

'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) );


Is it possible to set flag read =0 to read=1?

Yes. See further above.

--
Remy Lebeau (TeamB)

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)
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 11, 2017 5:43 PM   in response to: duf _ in response to: duf _
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)
duf _

Posts: 28
Registered: 7/2/06
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 11, 2017 10:40 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
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'
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 12, 2017 11:03 AM   in response to: duf _ in response to: duf _
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)
duf _

Posts: 28
Registered: 7/2/06
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 12, 2017 2:26 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
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 );
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 12, 2017 2:40 PM   in response to: duf _ in response to: duf _
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)
duf _

Posts: 28
Registered: 7/2/06
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 12, 2017 3:11 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

Did you change the value of the 2nd
parameter from StringToJString(L"_ID=" + smsid) to
StringToJString("_ID=?"), like I showed you?

No :D

This change and "content://sms" is all right and works perfect :)
I tried it on Android v.4.4.4

Thanks for Your patient
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 12, 2017 3:27 PM   in response to: duf _ in response to: duf _
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
duf _

Posts: 28
Registered: 7/2/06
Re: How to read SMS with C++ Builder in Android [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 16, 2017 3:05 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

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)

Server Response from: ETNAJIVE02