Sunday, October 27, 2013

How to fetch SMS messages from the Android inbox using Delphi

The code speaks for itself:

uses
  SysUtils,
  FMX.Helpers.Android,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Net,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Telephony;

function FetchSms:string;
var
  cursor: JCursor;
  uri: Jnet_Uri;
  address,person,msgdatesent,protocol,msgread,msgstatus,msgtype,
  msgreplypathpresent,subject,body,
  servicecenter,locked:string;
  msgunixtimestampms:int64;
  addressidx,personidx,msgdateidx,msgdatesentidx,protocolidx,msgreadidx,
  msgstatusidx,msgtypeidx,msgreplypathpresentidx,subjectidx,bodyidx,
  servicecenteridx,lockedidx:integer;
begin
  uri:=StrToJURI('content://sms/inbox');
  cursor := SharedActivity.getContentResolver.query(uri, nil, nil,nil,nil);
  addressidx:=cursor.getColumnIndex(StringToJstring('address'));
  personidx:=cursor.getColumnIndex(StringToJstring('person'));
  msgdateidx:=cursor.getColumnIndex(StringToJstring('date'));
  msgdatesentidx:=cursor.getColumnIndex(StringToJstring('date_sent'));
  protocolidx:=cursor.getColumnIndex(StringToJstring('protocol'));
  msgreadidx:=cursor.getColumnIndex(StringToJstring('read'));
  msgstatusidx:=cursor.getColumnIndex(StringToJstring('status'));
  msgtypeidx:=cursor.getColumnIndex(StringToJstring('type'));
  msgreplypathpresentidx:=cursor.getColumnIndex(StringToJstring('reply_path_present'));
  subjectidx:=cursor.getColumnIndex(StringToJstring('subject'));
  bodyidx:=cursor.getColumnIndex(StringToJstring('body'));
  servicecenteridx:=cursor.getColumnIndex(StringToJstring('service_center'));
  lockedidx:=cursor.getColumnIndex(StringToJstring('locked'));
  while (cursor.moveToNext) do begin
    address:=JStringToString(cursor.getString(addressidx));
    person:=JStringToString(cursor.getString(personidx));
    msgunixtimestampms:=cursor.getLong(msgdateidx);
    msgdatesent:=JStringToString(cursor.getString(msgdatesentidx));
    protocol:=JStringToString(cursor.getString(protocolidx));
    msgread:=JStringToString(cursor.getString(msgreadidx));
    msgstatus:=JStringToString(cursor.getString(msgstatusidx));
    msgtype:=JStringToString(cursor.getString(msgtypeidx));
    msgreplypathpresent:=JStringToString(cursor.getString(msgreplypathpresentidx));
    subject:=JStringToString(cursor.getString(subjectidx));
    body:=JStringToString(cursor.getString(bodyidx));
    servicecenter:=JStringToString(cursor.getString(servicecenteridx));
    locked:=JStringToString(cursor.getString(lockedidx));
    Result:=IntToStr(trunc(msgunixtimestampms/1000))+' '+address+' '+body;
  end;
end;

How to send SMS with Delphi on Android

Remember to go into Project/Options/Permissions and allow the app to send SMS. The code is:

uses
  FMX.Helpers.Android,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Net,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Telephony;

procedure SendSMS (target,messagestr:string);
var
  smsManager: JSmsManager;
  smsTo: JString;
begin
  smsManager:= TJSmsManager.JavaClass.getDefault;
  smsTo:= StringToJString(target);
  smsManager.sendTextMessage(smsTo, nil, StringToJString(messagestr), nil, nil);
end;

Getting started with Delphi XE5 and Android

This is a list of the problems that I experienced when I tried to use Delphi XE5 to make Android apps first time:

  1. My internet connection was not stable, so the Android NDK/SDK was not installed properly. This meant that I could not compile my source code. The solution was to run the "Android Tools" application which makes it easy to finish the installation.
  2. My Google Nexus 7 tablet could not be put into developer mode. The reason was that you need to tap the version number in the settings/about about 10 times before the device converts itself into a developer-device, which has developer settings.
  3. My Google Nexus S and Google Nexus 7 both connected well but in order to make Delphi XE5 run apps on it, you need to install the USB ADB driver. The "Android Tools" installs it on your harddisk, but not in Windows. I found a video on youtube that explained how to install the USB ADB driver, and how to configure Delphi XE5 to deploy to it.
  4. Finally, when all seemed right, it still did not deploy a sample Firemonkey app for mobile - instead, when running aadp with a huge command line parameter list, it returned "Error 1". The reason was, that you need to go into project/options/application and specify an application icon. Once I did that, the app deployed and started running on the phone.