Following on from my recent post about adding Android app splash screens in Delphi XE5 and Delphi XE6 I’ve now spent some time writing up details on how to launch various Android system activities. This includes the more interesting business of getting feedback from launched activities; a common use case here is using a barcode scanner and finding what barcode what scanned.
Again there are two articles, one for Delphi XE5 and one for Delphi XE6. The XE5 version is much longer as it involves documenting a whole bunch of command-line shenanigans (much like for the splash screen) to hook the activity results. This is made much easier in Delphi XE6, thankfully.
I’ve tried to do a thorough coverage of the subject matter, highlighting any issues I bumped into – I hope it is of use to anyone tinkering with Android apps in Delphi.
Hello! Thank you for this interesting series and let us make our hands dirty with examples of Delphi apps on android.
ReplyDeleteThere is a problem in the build.bat: it declares EMBO_DEX and EMBO_DEX_JAR to the same classes.dex (classes.jar supposed) and later in javac command line classes.jar is mentioned. Unfortunately, I haven't been able to find in XE5 and Appmethod 13.0 classes.jar
Because of that compile error happens
src\com\blong\test\NativeActivitySubclass.java:12: error: package com.embarcadero.firemonkey does not exist
public class NativeActivitySubclass extends com.embarcadero.firemonkey.FMXNativeActivity
Hi, glad you find interest in the write-ups.
DeleteIgnore EMBO_DEX_JAR - seems to be there in error. I'll fix that when I get chance.
classes.jar is created as one of the steps in the article, just before running build.bat; it's created by running a tool over classes.dex.
Search the web page of the article for classes.jar or for d2j-dex2jar and you'll see it.
Maybe I should have highlighted that a bit more clearly, one way or another... I'll see about making a change to announce what is needed.
Thank you! After dex2jar build.bat has run all right. It was my fault to run build.bat before this prep step #3.
DeleteCool, glad it's working!
DeleteHi Brian
ReplyDeleteThanks for this very interesting article.
I have one problem:
As soon as I call
SharedActivity.startActivityForResult(Intent,RequestCode);
my application terminates and there is no chance that HandleActivityMessage is ever called.
I am probably doing something wrong; but I have no idea what.
Thanks if you have an answer
Kaspar Neuenschwander, Switzerland
Seems like you'll need to run up DDMS or monitor from the Android SDK to check the logcat output from the app when it dies. That may give you the hint as to what step you have done wrong.
DeleteYou could also double check with my sample and see if that works or also fails.
Hello Brian:
ReplyDeleteThankx a lot for your interesting articles about xe6 and android.
Your source download link in "Launching activities and handling results in Delphi XE6 Android apps" article doesn't work.
It would be possible that your fix it?
I need to check your sample because i'm having a mistake when manage more than one activity in my project.
Thanks in advance.
José Manuel López
Hi there - the link has been fixed now.
DeleteGPS receiver switches off in sleep mode?
ReplyDeleteExemple:
I think that depends on how you write the app events. Generally many apps would benefit from disabling GPS updates when they go into the background, but I think in a Delphi app it's down to whether you choose to do so. I haven't tested the theory out yet.
DeleteI heard the AlarmManager you have any examples how to do in Delphi, Delphi exists in this JPendingIntent, JAlarmManager TJAlarmManager and more do not know how to implement. it exists in java:
ReplyDeletepublic class MyActivity extends Activity {
private PendingIntent pendingIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
/* Retrieve a PendingIntent that will perform a broadcast */
Intent alarmIntent = new Intent(MyActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MyActivity.this, 0, alarmIntent, 0);
findViewById(R.id.startAlarm).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
start();
}
});
findViewById(R.id.stopAlarm).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cancel();
}
});
findViewById(R.id.stopAlarmAt10).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startAt10();
}
});
}
public void start() {
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval = 8000;
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Toast.makeText(this, "Alarm Set", Toast.LENGTH_SHORT).show();
}
public void cancel() {
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.cancel(pendingIntent);
Toast.makeText(this, "Alarm Canceled", Toast.LENGTH_SHORT).show();
}
public void startAt10() {
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval = 1000 * 60 * 20;
/* Set the alarm to start at 10:30 AM */
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 10);
calendar.set(Calendar.MINUTE, 30);
/* Repeating on every 20 minutes interval */
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, pendingIntent);
}
}
Hello - I haven't seen any code that uses the Alarmmanager yet, but I'm hoping to get some time to look at working up an example myself at some point soon.
DeleteAny luck with AlarmManager?
DeleteAlas not. Sorry. WHat are you trying to do? I see on the Android docs page that if you want a timed event within your app's lifetime, a thread and Timer is recommended. However the alarm manager is to trigger events outside your app: http://developer.android.com/training/scheduling/alarms.html
DeleteHowever see the comment further down posted on 26 Feb '16 :)
Deletegood day
ReplyDeleteMy name is Luan
if you can help me with the question I'm grateful below:
Android gps background service Delphi xe6 or Xe7 or
GPS is going in sleep mode in Android Service or
GPS turning on after sleep mode
I'm not entirely sure what you are asking, but it sounds to me like you need to have a browse through the FMX Android source and see where the GPS support code is, and check what polling frequency is being employed.I think you can force the GPS to be continually polled using the LocationManager requestLocationUpdates method overload that takes a minTime argument (you can look that up on http://d.android.com )
DeleteIt may well be that the FMX code responds to the app going into the background and cancels the location update request - all supposition currently as I haven't scoured that section of the source as yet.
Bom dia deu certo usando esse código:
ReplyDeletefunction DateTimeLocalToUnixMSecGMT(const ADateTime: TDateTime): Int64;
begin
Result := DateTimeToUnix(ADateTime) * MSecsPerSec -
Round(TTimeZone.Local.UtcOffset.TotalMilliseconds);
end;
procedure Alarmmanager;
var
alarm:JIntent;
pendingIntent:JPendingIntent;
AlarmObj: JObject;
Alarmmanager: JAlarmManager;
Cada_Intervalo_Execute:Integer;
begin
{Para que Funcione Coloque isso no AndroidManifest.xml
Coloque esse procedimento em um time com inteval 1700
assim sua aplicação será excutado em BackBround/ Sleep Mode modo de Sono}
//Cada itervalo de Um segundo vai ser executado
//Como o time que tem a propriedade interval
//Cada_Intervalo_Execute:=1000; um segundo
//Verificar se o erro está qui
alarm := TJIntent.Create;
//No create já que o time sempre vai ficar executando
alarm.setClass(SharedActivityContext, Alarm.getClass);
pendingIntent:=TJPendingIntent.JavaClass.getService(
SharedActivityContext.getApplicationContext,1,alarm,0 );
AlarmObj :=SharedActivity.getSystemService(TJContext.JavaClass.ALARM_SERVICE);
Alarmmanager :=
TJAlarmManager.Wrap((AlarmObj as ILocalObject).GetObjectID);
Alarmmanager.setRepeating(
TJAlarmManager.JavaClass.ELAPSED_REALTIME_WAKEUP,
DateTimeLocalToUnixMSecGMT(Time),1000,pendingIntent);
end;
Ooh, very nice. Thanks for the post! When I get chance I will try this out :)
Deletein the example above... there are many things "undefined"... is there still no real working example of using ALARM_SERVICE in delphi even 4 years after this post? wow
ReplyDelete¯\_(ツ)_/¯
Delete