Why my Android app exit suddenly? - android

I am using Delphi 10.2 to create Android app that uses Rest components to read returning data from post form. When I press on a button to load the data it load them normally after about 3 seconds freeze. The problem if the user try to click (or touch) any control on the form the app exit immediately after the 3 seconds freeze but if the user did not touch the app the data was loaded normally !
What is the reason for that and how I should fix it ?
The code I use for the button is
RESTRequest1.Execute;
I use 3 components RESTClient , RESTRequest and RESTResponse
and here is the code I use to get the data:
procedure TfrmMain.RESTRequest1AfterExecute(Sender: TCustomRESTRequest);
var
return_response: string;
begin
if RESTResponse1.StatusCode = 200 then begin
//fill years
return_response := RESTResponse1.Content;
memo1.text := return_response;
end;
end.

On mobile platforms you should always use ExecuteAsync because it does not run in the same thread as the UI. Execute instead runs on the same thread as the UI so it freezes while the request is processing. Android closes the app if it is not responsive (= freezed) after some seconds, and this is your problem!
To be more precise, here's the doc:
The use of the ExecuteAsync method is strongly recommended on mobile
platforms. iOS (and likely Android) will terminate an application if
it considers the main thread to be unresponsive, i.e. if a running
request takes more than a second or two to return
You can find more info here.
The function ExecuteAsync, as you can see in the doc, has an useful parameter which takes an anonymous procedure. The code of this procedure will be called once the ExecuteAsync has finished his task. Here's an example:
RESTRequest1.ExecuteAsync(
procedure
begin
ShowMessage('Finished!');
end;);
This is very easy and also you don't need to type the other parameters since they alrady have a value by default. Again, if you look at the doc you'll see for example ASynchronized: Boolean = True;, so setting the second parameter after the anonymous proc to True would be not relevant.

Related

Doing Automated and manual testing in parallel in espresso in Android studio

Hi i have written testCases using espresso for the Android app.
Below is my code. my requirement is i need to manally Login to my app by entering credentials before i test the title bar Text.
So i am going into sleep for 2 min. when i enter credentials and click Login button below error is coming.
"D/InputEventConsistencyVerifier: TouchEvent: Touch event stream contains events from multiple sources: previous device id 0, previous source 2, new device id 0, new source 1002 "
Please let me know how to achieve this....
#Test
public void checkTitleBarText() throws InterruptedException {
sleep(120000);
onView(withId(R.id.drawer_layout)).perform(actionOpenDrawer());
Assert.assertEquals("SomeText", (String) textView.getText());
}
Why can't you just login with espresso? I'd be much easier...
However, If it's really your requirement, You can always launch tests with debuger attached and put a breakpoint in test code (which is stopping test thread). Login manually then and resume execution.

How to send a 'fake' command to Appium

I'm trying to test my android application with appium and I'm looking for a solution to the following issue:
In my application I have a section that takes time (for image processing) and it sometimes can take one minute, two minute or even more depends on the image size, quality.
In my test case I'm trying to wait for lets say 30 seconds and then I'm checking if the image processing is done.
The problem is if I'm waiting too long, I got the next message:
info: [debug] Didn't get a new command in 60 secs, shutting down...
I don't want to set a 'newCommandTimeout' cause I want to cut the test time and I want to test check if its done every short period.
In addition, I can't use the wait for element or something like that of appium API because I'm using a third party library which tells me when the image processing is done.
My questions is, there is any way to send a 'fake' command to appium so every 30 seconds that my thread is back to work and if I see that the image processing is not done I'll send a fake command and then go back to sleep for 30 seconds without any worry that the appium server will be shut down due to timeout?
Not sure what you are using for wait command. Use this:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
This will wait until it finds the element on screen.
In addition to the comment here:
In order to solve this issue I use the WebDriverWait with a custom ExpectedCondition and it looks like:
new WebDriverWait(mDriver, 30) // 30 is for the time out
.withMessage("You can set any custom error message")
.until(new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver d) {
//This function will be called repeatedly until
//the return value will be true
}
});
You can see other implementations of WebDriverWait and actually I think it works with any Object instead of Boolean.

App using Mobile Android GNSK crashes when identifyAlbumAsync() is called before audioProcessStart()

I have being upgrading an application to use the new Mobile Android GNSK but I have noticed that using the new MusicID-Stream is a little bit tricky. If the "identifyAlbumAsync" method get executed before the "audioProcessStart" method(since this need to be executed in a different thread), the application just crashes. In the Gracenote Demo application, the "audioProcessStart" method is continuously running so there is no need to synchronize its execution with the "identifyAlbumAsync" method call. Is it the way it is supposed to be used? It will be convenient if the application didn't crashed at least when the methods are not executed in order. Also in our application, we don't want to have the "audioProcessStart" method continuously like it is done in the demo application. We only want to run the "audioProcessStart" method when the user request identification and when the song playing gets identified , we want to stop the audio processing by calling "audioProcessStop". Is there an easy way to do this? Right now, we are getting the Thread where "identifyAlbumAsync" is running to sleep for 2 seconds in order to make sure that the Thread where the "audioProcessStart" method is supposed to run has time to get executed. Thank you in advance for your prompt response
In the upcoming 1.2 release, IGnMusicIdStreamEvents includes a callback that signals audio-processing has started, and an ID can be synced with this, e.g.:
#Override
public void musicIdStreamProcessingStatusEvent( GnMusicIdStreamProcessingStatus status, IGnCancellable canceller ) {
if (GnMusicIdStreamProcessingStatus.kStatusProcessingAudioStarted.compareTo(status) == 0) {
try {
gnMusicIdStream.identifyAlbumAsync();
} catch (GnException e) { }
}
}
Thanks for the feedback, you're right about this issue. Unfortunately right now sleeping is the best solution. But we are adding support for an explicit sync event in an upcoming release, please stay tuned.

How to wait in calabash-android for next activity if activity name is not known

Can I get any flag from calabash-android method which returns that page is still loading? I need to automate internet based application where wait is vary depending on internet speed and server load. How to set wait time or is there any way i will query to calabash-android which returns loading status of page.
You can use wait_for method. For instance:
wait_for(:timeout => 10, :retry_frequency => 0.2) { query("ProgressBar").empty? }
It waits for condition to be true until timeout runs out.

iOS equivalent to Android Service?

So with iOS 7 supporting a broader background mode, is it possible to finally have an equivalent to Android Service on iOS?
What I am after is essentially running app A in the background and have one or more apps B and C talk to that app (without showing the GUI of app A).
Please note that using connectivity and push notifications may not be an option although this is the recommended way of doing so.
Any ideas?
EDIT: Not working as expected. See this answer for best solution: Push Notifications
EDIT: The next solution is only useful while the user is in the app to maintain it synced.
There is no way to perform tasks in the background permanently, but you can use the finite-length tasks to do that, when you make a finite-length, this gonna run always while the app is active, but when you click home button, ios gives you only 10 min to perform your task and invalidate it, but it gives you a chance to make a 'invalidate handler block' where you can do last actions before finish definitely.
So, if you use that handler block to call a finite-length task other time, you can simulate a service by run a task for 10 min and when its end, call its same for other 10 min and consequently.
I use that in a project creating a interface 'Service'. I let you here the code:
Service.h
//
// Service.h
// Staff5Personal
//
// Created by Mansour Boutarbouch Mhaimeur on 30/09/13.
// Copyright (c) 2013 Smart & Artificial Technologies. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface Service : NSObject
#property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
#property (nonatomic) NSInteger frequency;
#property (nonatomic, strong) NSTimer *updateTimer;
- (id) initWithFrequency: (NSInteger) seconds;
- (void) startService;
- (void) doInBackground;
- (void) stopService;
#end
Service.m
//
// Service.m
// Staff5Personal
//
// Created by Mansour Boutarbouch Mhaimeur on 30/09/13.
// Copyright (c) 2013 Smart & Artificial Technologies. All rights reserved.
//
#import "Service.h"
#implementation Service
#synthesize frequency;
-(id)initWithFrequency: (NSInteger) seconds{
if(self = [super init]){
self.frequency = seconds;
return self;
}
return nil;
}
- (void)startService{
[self startBackgroundTask];
}
- (void)doInBackground{
//Español //Sobreescribir este metodo para hacer lo que quieras
//English //Override this method to do whatever you want
}
- (void)stopService{
[self.updateTimer invalidate];
self.updateTimer = nil;
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}
- (void) startBackgroundTask{
self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:frequency
target:self
selector:#selector(doInBackground)
userInfo:nil
repeats:YES];
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundTask];
}];
}
- (void) endBackgroundTask{
[self.updateTimer invalidate];
self.updateTimer = nil;
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
[self startBackgroundTask];
}
#end
With this class i perform my services, but i don't test it for a really long time. The best test i does lasted 16 hours in simulator and everything works fine!
EDIT: That was tested on the simulator, but in phone doesnt work after the application has been terminated.
I let you a example:
// SomeService.h
#interface SomeService : Service
#end
// SomeService.m
#import "SomeService.h"
#implementation SomeService
// The method to override
- (void)doInBackground{
NSLog(#"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
NSLog(#"Service running at %.1f seconds", [self getCurrentNetworkTime]);
}
// Your methods
- (long) getCurrentNetworkTime{
return ([[NSDate date] timeIntervalSince1970]);
}
#end
And in your app delegate or where you need to raise the service, you write the next line:
Service myService = [[SomeService alloc] initWithFrequency: 60]; //execute doInBackground each 60 seconds
[myService startService];
And if you need to stop it:
[myService stopService];
May have explained more than necessary, but i want to keep it clear for anyone!
I hope its help and sorry for my english.
No, there is no equivalent to an Android Service. MansApps code does not work, at least not on iOS7. A call of [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask]; in the expiration handler will only return when the app comes back to the foreground, i.e., the call of [self startBackgroundTask]; will not be executed when the app stays in the background.
Basically it's impossible if your app doesn't implement any of the functionalities listed bellow. And they hardly investigate your app before upload it to the store, you need to justify the use of that permissions
This is what Apple say about that:
Implementing Long-Running Tasks
For tasks that require more execution time to implement, you must request specific permissions to run them in the background without their being suspended. In iOS, only specific app types are allowed to run in the background:
Apps that play audible content to the user while in the background, such as a music player app
Apps that record audio content while in the background
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.
I found the best and standard solution:
Push notifications
(original post by Matthijs Hollemans, update by Ali Hafizji).
In iOS, apps can’t do a lot in the background. Apps are only allowed to do limited set of activities so battery life is conserved.
But what if something interesting happens and you wish to let the user know about this, even if they’re not currently using your app?
For example, maybe the user received a new tweet, their favorite team won the game, or their dinner is ready. Since the app isn’t currently running, it cannot check for these events.
Luckily, Apple has provided a solution to this. Instead of your app continuously checking for events or doing work in the background, you can write a server-side component to do this instead.
And when an event of interest occurs, the server-side component can send the app a push notification! There are three things a push notification can do:
Display a short text message
Play a brief sound
Set a number in a badge on the app’s icon
Tutorial link: http://maniacdev.com/2011/05/tutorial-ios-push-notification-services-for-beginners

Categories

Resources