掲示板

Android & LIferay: AsyncTask design

9年前 に Luciano Cauzzi によって更新されました。

Android & LIferay: AsyncTask design

New Member 投稿: 9 参加年月日: 15/03/18 最新の投稿
Hello everyone.
I write because I'm developing an Android App that uses Liferay as a backend.
Following the guides I found on this forum I set up two flavors of classes:

  • Liferay utility class: to manage connection to backend
  • Liferay request Asynctask: used to performs various requests


The code I used is attached to the post.
Now I have to face two problems:

  • Timeout: although it has specified a timeout of 5 seconds is not respected by the application
  • Callback: within dell'asyncTask I specified a callback to monitor the status of the request. The basic idea is to keep running asynctask's reference to retrieve the data and still allow the user to change screen, separating the phase of updating data from the GUI. Now, in case the network request fails, the callback works as exspected but fails while invoking the asyncTask's cancel() method because the latter has since finished its execution. Consequently the AsyncTask ends properly in every running scenario and I can not setup the behaviour on onCanceled() method. Consequently, the only solution I found is to create the callback in the context of GUI (Eg activity / fragment)


Am I running the invocations properly or did I miss something along the way?

Thank you for your support and for the help

Luciano
thumbnail
9年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
Hi Luciano,

Regarding your connection timeout issue, I've created a test case for it:

ConnectionTimeoutTest.java

I've set the connection timeout to 5ms and I'm getting "ConnectionTimeoutException" as expected, since that timeout is very small. Can you write a test that reproduces your issue? You can change and run this test by running from the "liferay-mobile-sdk/android" folder:

../gradlew -Dtest.single=ConnectionTimeoutTest test

Regarding your second question, about callbacks. I don't understand why you are creating 2 callbacks inside the doInBackground method. This method already runs in a thread different than the Android's main thread, there's no need to create callbacks inside that method, just do synchronous requests, like the sample does:

UsersAsyncTask.java

I think you are having issues because you are running more than one thread at the same time and is expecting they will somehow wait for each other.
9年前 に Luciano Cauzzi によって更新されました。

RE: Android & LIferay: AsyncTask design

New Member 投稿: 9 参加年月日: 15/03/18 最新の投稿
Dear Bruno,
Thank you for your response. I tried to run the test you asked me and I have complied this output:

 ../gradlew -Dtest.single=ConnectionTimeoutTest test --info

Starting Build
Settings evaluated using settings file '/Users/lcauzzi/Documents/Progetti/Android/Tea/liferay/liferay/settings.gradle'.
Projects loaded. Root project using build file '/Users/lcauzzi/Documents/Progetti/Android/Tea/liferay/liferay/build.gradle'.
Included projects: [root project 'liferay', project ':android', project ':builder', project ':ios', project ':modules/calendar-portlet', project ':modules/push-notifications-portlet', project ':modules/sync-web']
Evaluating root project 'liferay' using build file '/Users/lcauzzi/Documents/Progetti/Android/Tea/liferay/liferay/build.gradle'.
Evaluating project ':android' using build file '/Users/lcauzzi/Documents/Progetti/Android/Tea/liferay/liferay/android/build.gradle'.
Evaluating project ':builder' using build file '/Users/lcauzzi/Documents/Progetti/Android/Tea/liferay/liferay/builder/build.gradle'.
Evaluating project ':ios' using build file '/Users/lcauzzi/Documents/Progetti/Android/Tea/liferay/liferay/ios/build.gradle'.
Evaluating project ':modules/calendar-portlet' using empty build file.
Evaluating project ':modules/push-notifications-portlet' using empty build file.
Evaluating project ':modules/sync-web' using empty build file.
All projects evaluated.
Selected primary task 'test'
Tasks to be executed: [task ':android:compileJava', task ':android:processResources', task ':android:classes', task ':android:compileTestJava', task ':android:processTestResources', task ':android:testClasses', task ':android:test']
:android:compileJava (Thread[main,5,main]) started.
:android:compileJava
Skipping task ':android:compileJava' as it is up-to-date (took 0.653 secs).
:android:compileJava UP-TO-DATE
:android:compileJava (Thread[main,5,main]) completed. Took 0.695 secs.
:android:processResources (Thread[main,5,main]) started.
:android:processResources
Skipping task ':android:processResources' as it has no source files.
:android:processResources UP-TO-DATE
:android:processResources (Thread[main,5,main]) completed. Took 0.002 secs.
:android:classes (Thread[main,5,main]) started.
:android:classes
Skipping task ':android:classes' as it has no actions.
:android:classes UP-TO-DATE
:android:classes (Thread[main,5,main]) completed. Took 0.003 secs.
:android:compileTestJava (Thread[main,5,main]) started.
:android:compileTestJava
Skipping task ':android:compileTestJava' as it is up-to-date (took 0.088 secs).
:android:compileTestJava UP-TO-DATE
:android:compileTestJava (Thread[main,5,main]) completed. Took 0.097 secs.
:android:processTestResources (Thread[main,5,main]) started.
:android:processTestResources
Skipping task ':android:processTestResources' as it is up-to-date (took 0.004 secs).
:android:processTestResources UP-TO-DATE
:android:processTestResources (Thread[main,5,main]) completed. Took 0.011 secs.
:android:testClasses (Thread[main,5,main]) started.
:android:testClasses
Skipping task ':android:testClasses' as it has no actions.
:android:testClasses UP-TO-DATE
:android:testClasses (Thread[main,5,main]) completed. Took 0.003 secs.
:android:test (Thread[main,5,main]) started.
:android:test
Skipping task ':android:test' as it is up-to-date (took 0.096 secs).
:android:test UP-TO-DATE
:android:test (Thread[main,5,main]) completed. Took 0.145 secs.

BUILD SUCCESSFUL

Total time: 7.672 secs
Stopped 0 compiler daemon(s).


In addition I tried to lower the timeout to 5 in my project on Android Studio: the portion of code with which I maked the request is contained in a try-catch block but the exception never occurs.

In my example there was two callbacks because I tried different request without success: when I set the callback, I receive an empty response and the asyncTask ends correctly.

Where am I wrong?
9年前 に Luciano Cauzzi によって更新されました。

RE: Android & LIferay: AsyncTask design

New Member 投稿: 9 参加年月日: 15/03/18 最新の投稿
I had also written a simple test case in AS as follows:


public class TestCase extends InstrumentationTestCase {

    private static final int CON_TIMEOUT = 1;

    public void testTimeout() throws Exception{
        BasicAuthentication basicAuthentication = new BasicAuthentication("user", "passsword");

        //METHOD 1
         //Session sessionImpl = new SessionImpl("http://domain.com", basicAuthentication);
        //sessionImpl.setConnectionTimeout(CON_TIMEOUT);

        //METHOD 2
        Session session = new SessionImpl("http://domain.com", basicAuthentication, CON_TIMEOUT, null);

    }

}

but no Exception was raised during test in both "method 1" and "method 2"
thumbnail
9年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
Hi Luciano,

In your test, you are not calling a service, thus you are not making any requests, that's why you are not getting connection timeout exceptions.

Creating SessionImpl instances doesn't do much, there's no communication being done with the server until a service is actually called.
9年前 に Luciano Cauzzi によって更新されました。

RE: Android & LIferay: AsyncTask design

New Member 投稿: 9 参加年月日: 15/03/18 最新の投稿
The problem still persist in my application although I invoke the service.
Also the working version of the application has been affected and also by changing the test as you can see below, the result is always the same.

No exception

// -- new Test case
public void testTimeout() throws Exception{

Logger.e("Test timeout");

BasicAuthentication basicAuthentication = new BasicAuthentication("user", "password");

Session session = new SessionImpl("http://domain.com", basicAuthentication);
session.setConnectionTimeout(1);

ClassNameService classNameService = new ClassNameService(session);
GroupService groupService = new GroupService(session);


JSONObject nameArray = classNameService.fetchClassName(CLASS_NAME_RESOURCE);
long portalInstance = Long.parseLong("10364");
JSONArray groupJsonArray = groupService.getGroups(portalInstance, 0l, true);


}
thumbnail
9年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
I ran the exact same test you pasted and got timeout exception. To be precise, when I ran with 1ms, I get a different exception: HttpHostConnectException. But that's fine, since in practice no one would set the timeout to 1ms, unless you are really willing to force an exception.

Are you running against localhost? If so, perhaps the response is so fast that there isn't really a timeout. That's why in my test case I'm using www.liferay.com, because for sure it will take more than 5ms.
9年前 に Luciano Cauzzi によって更新されました。

RE: Android & LIferay: AsyncTask design

New Member 投稿: 9 参加年月日: 15/03/18 最新の投稿
No, unfortunately I'm not running the test in localhost and I can not figure out exactly what happens. Next week I will make other evidence about it on different machines with my colleagues.

Meanwhile, thanks for the support
9年前 に Luciano Cauzzi によって更新されました。

RE: Android & LIferay: AsyncTask design

New Member 投稿: 9 参加年月日: 15/03/18 最新の投稿
I tried to import the module in Android development environment IntelliJ Idea and I created test Main Class (Main.java) for invoking service.
The code is almost identical to that used in Android Studio.

I have included the dependencies listed in android.iml file:

<!--?xml version="1.0" encoding="UTF-8"?-->
<module type="JAVA_MODULE" version="4">
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourcefolder url="file://$MODULE_DIR$/src" isTestSource="false" />
    </content>
    <orderentry type="inheritedJdk" />
    <orderentry type="sourceFolder" forTests="false" />
    <orderentry type="library" name="org.apache.httpcomponents:httpmime:4.3.3" level="project" />
    <orderentry type="library" name="commons-codec:commons-codec:1.10" level="project" />
    <orderentry type="library" name="org.apache.httpcomponents:httpclient-android:4.3.3" level="project" />
    <orderentry type="library" name="com.liferay.mobile:liferay-android-sdk:6.2.0.15" level="project" />
  </component>
</module>



When I run the code with timeout setted to one, then I got the exception as expected.

Where did you run your tests?

添付ファイル:

thumbnail
9年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
Luciano,

You already ran the test when you did "../gradlew (...) test". As you pasted in this thread, the build was successful, which means the test didn't fail. You don't need to import the project to IntelliJ to run tests.
thumbnail
8年前 に Denis Signoretto によって更新されました。

RE: Android & LIferay: AsyncTask design

Expert 投稿: 375 参加年月日: 09/04/21 最新の投稿
Hi Bruno,

I suppose we are facing with an issue of httpclient-android. I've investigated the issue adding to your test some code to understand which version of HttpClient interface it's loaded during test execution

HttpClient client = HttpUtil.getClient(session);
            URL location = client.getClass().getResource('/'+ client.getClass().getName().replace('.', '/')+".class");
            System.out.println(client.getClass().getCanonicalName() + " " + location);


and I've seen that ConnectionTimeout test is executed with apache "org.apache.httpcomponents:httpclient:4.3.3".

compile - Compile classpath for source set 'main'.
+--- com.google.android:android:2.3.3
|    +--- commons-logging:commons-logging:1.1.1 -&gt; 1.1.3
|    +--- org.apache.httpcomponents:httpclient:4.0.1 -&gt; 4.3.3
|    |    +--- org.apache.httpcomponents:httpcore:4.3.2
|    |    +--- commons-logging:commons-logging:1.1.3
|    |    \--- commons-codec:commons-codec:1.6
|    +--- org.khronos:opengl-api:gl1.1-android-2.1_r1
|    +--- xerces:xmlParserAPIs:2.6.2
|    +--- xpp3:xpp3:1.1.4c
|    \--- org.json:json:20080701
+--- org.apache.httpcomponents:httpclient-android:4.3.3
\--- org.apache.httpcomponents:httpmime:4.3.3
     \--- org.apache.httpcomponents:httpclient:4.3.3 (*)

default - Configuration for default artifacts.
+--- com.google.android:android:2.3.3
|    +--- commons-logging:commons-logging:1.1.1 -&gt; 1.1.3
|    +--- org.apache.httpcomponents:httpclient:4.0.1 -&gt; 4.3.3
|    |    +--- org.apache.httpcomponents:httpcore:4.3.2
|    |    +--- commons-logging:commons-logging:1.1.3
|    |    \--- commons-codec:commons-codec:1.6
|    +--- org.khronos:opengl-api:gl1.1-android-2.1_r1
|    +--- xerces:xmlParserAPIs:2.6.2
|    +--- xpp3:xpp3:1.1.4c
|    \--- org.json:json:20080701
+--- org.apache.httpcomponents:httpclient-android:4.3.3
\--- org.apache.httpcomponents:httpmime:4.3.3
     \--- org.apache.httpcomponents:httpclient:4.3.3 (*)

formatter
Download http://repo1.maven.org/maven2/com/liferay/portal/portal-impl/6.2.0-ga1/portal-impl-6.2.0-ga1.pom
+--- com.liferay.portal:portal-impl:6.2.0-ga1
+--- com.liferay.portal:portal-service:6.2.0-ga1
+--- com.liferay.portal:util-java:6.2.0-ga1
+--- dom4j:dom4j:1.6.1
|    \--- xml-apis:xml-apis:1.0.b2
\--- org.apache.ant:ant:1.8.2
     \--- org.apache.ant:ant-launcher:1.8.2

runtime - Runtime classpath for source set 'main'.
+--- com.google.android:android:2.3.3
|    +--- commons-logging:commons-logging:1.1.1 -&gt; 1.1.3
|    +--- org.apache.httpcomponents:httpclient:4.0.1 -&gt; 4.3.3
|    |    +--- org.apache.httpcomponents:httpcore:4.3.2
|    |    +--- commons-logging:commons-logging:1.1.3
|    |    \--- commons-codec:commons-codec:1.6
|    +--- org.khronos:opengl-api:gl1.1-android-2.1_r1
|    +--- xerces:xmlParserAPIs:2.6.2
|    +--- xpp3:xpp3:1.1.4c
|    \--- org.json:json:20080701
+--- org.apache.httpcomponents:httpclient-android:4.3.3
\--- org.apache.httpcomponents:httpmime:4.3.3
     \--- org.apache.httpcomponents:httpclient:4.3.3 (*)

signatures
No dependencies

testCompile - Compile classpath for source set 'test'.
+--- com.google.android:android:2.3.3
|    +--- commons-logging:commons-logging:1.1.1 -&gt; 1.1.3
|    +--- org.apache.httpcomponents:httpclient:4.0.1 -&gt; 4.3.3
|    |    +--- org.apache.httpcomponents:httpcore:4.3.2
|    |    +--- commons-logging:commons-logging:1.1.3
|    |    \--- commons-codec:commons-codec:1.6
|    +--- org.khronos:opengl-api:gl1.1-android-2.1_r1
|    +--- xerces:xmlParserAPIs:2.6.2
|    +--- xpp3:xpp3:1.1.4c
|    \--- org.json:json:20080701
+--- org.apache.httpcomponents:httpmime:4.3.3
|    \--- org.apache.httpcomponents:httpclient:4.3.3 (*)
\--- junit:junit:4.12-beta-3
     \--- org.hamcrest:hamcrest-core:1.3

testRuntime - Runtime classpath for source set 'test'.
+--- com.google.android:android:2.3.3
|    +--- commons-logging:commons-logging:1.1.1 -&gt; 1.1.3
|    +--- org.apache.httpcomponents:httpclient:4.0.1 -&gt; 4.3.3
|    |    +--- org.apache.httpcomponents:httpcore:4.3.2
|    |    +--- commons-logging:commons-logging:1.1.3
|    |    \--- commons-codec:commons-codec:1.6
|    +--- org.khronos:opengl-api:gl1.1-android-2.1_r1
|    +--- xerces:xmlParserAPIs:2.6.2
|    +--- xpp3:xpp3:1.1.4c
|    \--- org.json:json:20080701
+--- org.apache.httpcomponents:httpmime:4.3.3
|    \--- org.apache.httpcomponents:httpclient:4.3.3 (*)
\--- junit:junit:4.12-beta-3
     \--- org.hamcrest:hamcrest-core:1.3


Executing the same test with Robolectric that loads
org/apache/httpcomponents/httpclient-android/4.3.3/httpclient-android-4.3.3.jar!/org/apache/http/impl/client/InternalHttpClient.class

the test fails. I think a trial on a physical device can help to verify definitively the issue.

I've seen you are introducing okHttp. Do you aspect it can solve this issue ?
In the meanwhile i think it should be opened on Jira, do you agree?

Thanks,
Bye,
Denis.
thumbnail
8年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
Hey Dennis,

We have already moved to OkHttp, I haven't publicly announced it because it needs some documentation changes (mainly the upload/download part, all other APIs should work the same).

You can try it out:

compile group: 'com.liferay.mobile', name: 'liferay-android-sdk', version: '2.0.2'

As you see, we switched back to a better versioning scheme (2.0.2). We have been using it with internal apps and has been working great, it fixes all test issues too since there's no android/robolectric dependency.
thumbnail
8年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
Hey Dennis,

I think I didn't make it clear this version is still in beta even though it seems to be working fine, that's another reason why we haven't publicly announced it too.

Do you want to give it a try? Let me know if you run into any issues.
thumbnail
8年前 に Denis Signoretto によって更新されました。

RE: Android & LIferay: AsyncTask design

Expert 投稿: 375 参加年月日: 09/04/21 最新の投稿
Hi Bruno!

thanks for your answer and your clarifications. Initially I saw 2.0.2 but I was thinking it was an earlier version.
Happy to hear it's the "newest" version and it uses OkHttp implementation with removals of old android dependencies.

I've just switched our "test project" from liferay-android-sdk 6.2.0.22 to 2.0.2 and seems to work fine (all previous tests passed).
I had to do a little refactory of some async task classes. I'll test more the application with new library in the next days, if I''ll find issues I'll let you know.

Last but not least time out connection is handled correcly (test and device behave as expected). Solved!

Thanks!

Bye,
Denis.

P.S. Waiting your annoncement ;)
thumbnail
8年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
Thanks for trying it out, Dennis, your feedback will be important.

The only thing that I think I should warn you is that async requests are not queued up anymore as before, OkHttp will run them all in parallel, it might change your app behavior a little bit.

Now you can also cancel sent requests too, which is also very cool (HttpUtil.cancel(request)).

This move to OkHttp was ignited our Android lead, Silvio Santos, all props should go to him.

We renamed the version scheme because we didn't want to make other clients upgrade automatically without noticing (if their dependency was pointing to 6.2.0.+).
thumbnail
8年前 に Denis Signoretto によって更新されました。

RE: Android & LIferay: AsyncTask design

Expert 投稿: 375 参加年月日: 09/04/21 最新の投稿
Bruno Farache:

We renamed the version scheme because we didn't want to make other clients upgrade automatically without noticing (if their dependency was pointing to 6.2.0.+).


Good!

About versioning scheme, looking at Maven Repository (http://search.maven.org/#search|ga|1|com.liferay.mobile) the old scheme is still reported as the "latest" version. It can cause users to fall in error.

Bye,
Denis.
thumbnail
8年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
This is actually good because we don't want them to upgrade to OkHttp without noticing.

But yes, it will be a problem when we finally decide to release it publicly emoticon. One solution would be to rename the artifactId from "liferay-android-sdk" to something else, any other idea?
thumbnail
8年前 に Denis Signoretto によって更新されました。

RE: Android & LIferay: AsyncTask design

Expert 投稿: 375 参加年月日: 09/04/21 最新の投稿
Mmmm...
If you don't want change the artifactId you can choose a number greater than 6, e.g. 7 (or 7.0)!
The drawback about 7 is that it can be a little misleading, due to coincidence with imminent Liferay 7; someone can think that it's a version supported only by Liferay 7 and I guess you would like a numer that reflect the real history (doesn't exist versions 1,..,5).

IMHO I think a good solution is change the artifact id and use new major version starting from 2 and use identifiers for betas e.g. 2.0.2-beta1.

Bye,
Denis.
thumbnail
8年前 に Bruno Farache によって更新されました。

RE: Android & LIferay: AsyncTask design

Liferay Master 投稿: 603 参加年月日: 07/05/14 最新の投稿
Had an idea, for portal 7.0, we can use the same Mobile SDK core and just generate the services for that specific version. Then, we would have 3 artifacts:

liferay-android-sdk-core.jar (version 2.0.3)
liferay-android-sdk-v62.jar (we can have several versions for this one, each version would be compatible with a specific 6.2.x portal version)
liferay-android-sdk-v7.jar (compatible with 7.0.x)

By importing core, you would probably get the other 2 artifacts as dependencies (latest 6.2.x and 7.0.x versions).

This version scheme actually makes a lot of sense, we can evolve the core independently of portal versions (for example, using OkHttp, which has nothing to do with portal versions), while you can still choose which generated services works with your specific portal version. How that sounds?
thumbnail
8年前 に Denis Signoretto によって更新されました。

RE: Android & LIferay: AsyncTask design

Expert 投稿: 375 参加年月日: 09/04/21 最新の投稿
+1 !!!

This is exactly what I'm doing organizing mobile sdk project, where generated API I tend to organize in a transitive independent library.

Bye!
Denis