Fails to map api response to pojo when enabling multidex - android

I'm writing an Android application with lots of dependencies and I needed to enable multidex because it exceeds the limit (65536k methods). I followed this guide and able to compile and run the application on my test device. The problem is I'm getting a nullpointerexception in Robospice RequestListener
for every api call that I make. I'm sure that the api is responding. It seems that the app fails to map the response to my pojo class.
Note: It's running fine before I enabled the multidex.
here is the request listener
private class MyRequestListener implements RequestListener<PojoClass> {
#Override
public void onRequestFailure(SpiceException e) {
}
#Override
public void onRequestSuccess(PojoClass pojoClass) {
// pojoClass <---- this is null
}
}
here are my dependencies for rest and mapping
'org.springframework.android:spring-android-rest-template:2.0.0.M1'
'com.octo.android.robospice:robospice-spring-android:1.4.14'
'org.codehaus.jackson:jackson-core-asl:1.9.13'
'org.codehaus.jackson:jackson-mapper-asl:1.9.13'
Any suggestions

Related

GoogleApiClient builder failing to build

I'm implementing Google Smart Lock into an app, and I was having no trouble with the Api Client building before. In fact, I was finalizing some syntax changes and cleaning up the code (didn't even touch the code that initializes the Api Client), and my app now dies when build() is called on the Api Client builder, due to abstract method zza. Here is the error being displayed:
java.lang.AbstractMethodError: abstract method "com.google.android.gms.common.api.Api$zze com.google.android.gms.common.api.Api$zza.zza(android.content.Context, android.os.Looper, com.google.android.gms.common.internal.zzq, java.lang.Object, com.google.android.gms.common.api.GoogleApiClient$ConnectionCallbacks, com.google.android.gms.common.api.GoogleApiClient$OnConnectionFailedListener)"
at com.google.android.gms.common.api.GoogleApiClient$Builder.build(Unknown Source)
I have no clue why it suddenly started failing, and I couldn't find any changes I made that would have caused this error. Why isn't that abstract method being overridden? It's nested deep inside the library so I don't understand how I could have affected it.
I wrapped the Google Api Client calls in a manager I named CredentialManager. Here is the code I used to initialize the client:
public CredentialManager(ContextProvider contextProvider) {
mContextProvider = contextProvider;
mCredentialsApiClient = new GoogleApiClient.Builder(mContextProvider.getContext())
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(CredentialManager.TAG, "Api connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.i(CredentialManager.TAG, "Connection suspended with status " + i);
}
})
.enableAutoManage(mContextProvider.getContext(), connectionFailedResult -> {
if (connectionFailedResult.hasResolution()) {
try {
connectionFailedResult.startResolutionForResult(
mContextProvider.getContext(),
CredentialManager.Codes.RESOLVE_CONNECTION_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
// Unable to resolve, log error
Log.e(CredentialManager.TAG, "Resolution failed: " + e.getMessage());
}
} else {
//instead of displaying a dialog, just let the user continue and login manually.
Log.e(CredentialManager.TAG, "Connection failed: " + connectionFailedResult.getErrorMessage());
}
})
.addApi(Auth.CREDENTIALS_API)
.build();
}
If you have any insight as to what is causing this error, please let me know. I've scoured the internet for anyone that has seen something like this before, but couldn't find anything.
The issue was that some google play services dependencies had their versions updated and not the play-services-auth dependency used for google smart lock. The apk would compile fine, but crash when the Google Api Client was trying to initialize. The fix was to make all the versions the same, and invalidate cache + restart android studio, recompile, and run.

grpc server on Android

I am trying to build a platform agnostic communication channel between a provider and consumer processes. Found grpc + protobuf to be a good option.
Is there an example or implementation of GRPC server (Java/C++) running on Android?
I am following grpc java server example to implement the server i
private class GrpcServerTask extends AsyncTask<Void, Void, String>{
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
int port = 50051;
Server server;
try {
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
#Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
I keep getting the error
io.grpc.ManagedChannelProvider$ProviderNotFoundException: No functional server found. Try adding a dependency on the grpc-netty artifact
on executing new GrpcServerTask().execute();
Thanks
Netty server on Android isn't really supported. Android's garbage collector and NIO support are both too poor for good Netty performance. Also some things are unlikely to work, like TLS. If it is just for testing on the newest Android release it may mostly work, but no guarantees that it works now or continues to work in the future.
With that in mind, make sure that you have a dependency on grpc-netty and try without ProGuard as a test. ProGuard's renaming and stripping both can cause trouble; you would need -keepnames io.grpc.ServerProvider and -keep io.grpc.netty.NettyServerProvider in your ProGuard rules, like was done for client-side.
C++ in another option. Client-side has been used on Android already, and I would expect server-side to function if you get client-side working. But I'm also not as aware of the C++ implementation.

How to add JSON Parser libraries?

I want to use the JSONParser codes but when I write the codes some imports are wrong or it's marked by red.What I have to do?
try using the volley library. this will remvoe all your headache of using the JSONParser class to get the json from the url and so on.
Please refer this link for volley:
http://www.androidhive.info/2014/09/android-json-parsing-using-volley/
.. Let me know if this helps ! :)
Have you added the dependency to your project? If not, write this line to your build.gradle file
compile 'org.apache.httpcomponents:httpcore:4.0-beta3'
For Http Client, add this dependency for your project:
compile 'org.apache.httpcomponents:httpclient:4.5.1'
Besides, that library was deprecated. You should use HttpUrlConnection instead.
TIP: If you want to import some library (dependency), just copy that library package(e.g. org.apache.http.HttpEntity) + "dependency" then type to Google :D
Try using Fast Android Networking Library
Add this dependency to your build.gradle (app level)
compile 'com.amitshekhar.android:android-networking:1.0.0'
Add internet permission in manifest
For GET Method
AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllUsers/{pageNumber}")
.addPathParameter("pageNumber", "0")
.addQueryParameter("limit", "3")
.addHeaders("token", "1234")
.setTag("test")
.setPriority(Priority.LOW)
.build()
.getAsJSONArray(new JSONArrayRequestListener() {
#Override
public void onResponse(JSONArray response) {
// do anything with response
}
#Override
public void onError(ANError error) {
// handle error
}
});
For POST method
AndroidNetworking.post("https://fierce-cove-29863.herokuapp.com/createAnUser")
.addBodyParameter("firstname", "Amit")
.addBodyParameter("lastname", "Shekhar")
.setTag("test")
.setPriority(Priority.MEDIUM)
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
#Override
public void onResponse(JSONObject response) {
// do anything with response
}
#Override
public void onError(ANError error) {
// handle error
}
});
documentation here: https://github.com/amitshekhariitbhu/Fast-Android-Networking
While adding JSONParser you may get some errors, kindly do this two step:
For me the path was like: C:\Users\vaidu\Instructable2\app\build.gardle
Add this two things to buildgradle file
android {
useLibrary 'org.apache.http.legacy'}
dependencies{ compile 'com.android.support:appcompat-v7:26.1.0' }

Particular overload of Azure Mobile Service invokeApi is not working while calling custom API

Where is the documentation/sample for all overloads of invokeApi function for Azure Mobile Service client SDK for Android?
I found this article and tried following code, which does not work. There are no compile time or run time errors, invokeApi gets called, but it does not come back to onSuccess or onFailure. If I call invokeApi without order object, everything works as expected
PizzaOrder order = new PizzaOrder();
order.Size = "Large";
order.Flavor = "Four cheeses";
order.UserPhone = "555-555-1234";
ListenableFuture<PizzaOrderResponse> testresult = mClient.invokeApi("bookservice", order, PizzaOrderResponse.class);
Futures.addCallback(testresult, new FutureCallback<PizzaOrderResponse>() {
#Override
public void onFailure(Throwable exc) {
// failure handling code here
}
#Override
public void onSuccess(PizzaOrderResponse testresult) {
// success handling code here
}
});
One of the properties in the data object being returned by the custom API had incorrect data type. I am still not sure where the good documentation is and why custom API call did not fail but at least it is working now.

How to unit test Retrofit api calls?

I am trying to integrate Unit test cases for every chunk of code possible.
But I am facing issues while adding test cases for api calls that are made through retrofit.
The JUnit compiler never executes the code in the CallBack functions.
There is another option of making all the api calls Synchronous for testing purpose, but that's not possible for every case in my app.
How can I sort this out? I have to add test cases in the api calls by any means.
If you use .execute() instead of .enqueue() it makes execution synchron, thus the tests can ran properly without the need of importing 3 different libraries and adding any code or modify the build variants.
Like:
public class LoginAPITest {
#Test
public void login_Success() {
APIEndpoints apiEndpoints = RetrofitHelper.getTesterInstance().create(APIEndpoints.class);
Call<AuthResponse> call = apiEndpoints.postLogin();
try {
//Magic is here at .execute() instead of .enqueue()
Response<AuthResponse> response = call.execute();
AuthResponse authResponse = response.body();
assertTrue(response.isSuccessful() && authResponse.getBearer().startsWith("TestBearer"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
I test my Retrofit callbacks using Mockito, Robolectric and Hamcrest libraries.
First of all, set up lib stack in your module's build.gradle:
dependencies {
testCompile 'org.robolectric:robolectric:3.0'
testCompile "org.mockito:mockito-core:1.10.19"
androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
}
In jour project's global build.gradle add following line to buildscript dependencies:
classpath 'org.robolectric:robolectric-gradle-plugin:1.0.1'
Then enter "Build Variants" menu in Android Studio (to quickly find it, hit Ctrl+Shift+A and search for it), and switch "Test Artifact" option to "Unit Tests". Android studio will switch your test folder to "com.your.package (test)" (instead of androidTest).
Ok. Set-up is done, time to write some tests!
Let's say you've got some retrofit api calls to retrieve a list of objects that need to be put into some adapter for a RecyclerView etc. We would like to test whether adapter gets filled with proper items on successful call.
To do this, we'll need to switch your Retrofit interface implementation, that you use to make calls with a mock, and do some fake responses taking advantage of Mockito ArgumentCaptor class.
#Config(constants = BuildConfig.class, sdk = 21,
manifest = "app/src/main/AndroidManifest.xml")
#RunWith(RobolectricGradleTestRunner.class)
public class RetrofitCallTest {
private MainActivity mainActivity;
#Mock
private RetrofitApi mockRetrofitApiImpl;
#Captor
private ArgumentCaptor<Callback<List<YourObject>>> callbackArgumentCaptor;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ActivityController<MainActivity> controller = Robolectric.buildActivity(MainActivity.class);
mainActivity = controller.get();
// Then we need to swap the retrofit api impl. with a mock one
// I usually store my Retrofit api impl as a static singleton in class RestClient, hence:
RestClient.setApi(mockRetrofitApiImpl);
controller.create();
}
#Test
public void shouldFillAdapter() throws Exception {
Mockito.verify(mockRetrofitApiImpl)
.getYourObject(callbackArgumentCaptor.capture());
int objectsQuantity = 10;
List<YourObject> list = new ArrayList<YourObject>();
for(int i = 0; i < objectsQuantity; ++i) {
list.add(new YourObject());
}
callbackArgumentCaptor.getValue().success(list, null);
YourAdapter yourAdapter = mainActivity.getAdapter(); // Obtain adapter
// Simple test check if adapter has as many items as put into response
assertThat(yourAdapter.getItemCount(), equalTo(objectsQuantity));
}
}
Proceed with the test by right clicking the test class and hitting run.
And that's it. I strongly suggest using Robolectric (with robolectric gradle plugin) and Mockito, these libs make testing android apps whole lotta easier.
I've learned this method from the following blog post. Also, refer to this answer.
Update: If you're using Retrofit with RxJava, check out my other answer on that too.
The JUnit framework never executes the code in the CallBack functions because the main thread of execution terminates before the response is retrieved. You can use CountDownLatch as shown below:
#Test
public void testApiResponse() {
CountDownLatch latch = new CountDownLatch(1);
mApiHelper.loadDataFromBackend(new Callback() {
#Override
public void onResponse(Call call, Response response) {
System.out.println("Success");
latch.countDown();
}
#Override
public void onFailure(Call call, Throwable t) {
System.out.println("Failure");
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This test sample may be helpful too.
My advice isn't to perform testing for the API responses in the android app. There are many external tools for this.
Junit will not wait for async tasks to complete. You can use CountDownLatch (elegant solution which does NOT require an external library) to block the thread, until you receive response from server or timeout.
You can use CountDownLatch.
The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately.
//Step 1: Do your background job
latch.countDown(); //Step 2 : On completion ; notify the count down latch that your async task is done
latch.await(); // Step 3: keep waiting
OR you can specify a timeout in your await call
try {
latch.await(2000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
Sample Test Case
void testBackgroundJob() {
Latch latch = new CountDownLatch(1);
//Do your async job
Service.doSomething(new Callback() {
#Override
public void onResponse(){
ACTUAL_RESULT = SUCCESS;
latch.countDown(); // notify the count down latch
// assertEquals(..
}
});
//Wait for api response async
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
assertEquals(expectedResult, ACTUAL_RESULT);
}
if already encapsulation retrofit2.0 with rx with restful
open class BaseEntity<E> : Serializable {
/*result code*/
var status: Int = 0
/**data */
var content: E? = null
}
and server api request like
#GET(api/url)
fun getData():Observable<BaseEntity<Bean>>
your service call back just one sync request Observable
val it = service.getData().blockingSingle()
assertTrue(it.status == SUCCESS_CODE)
As #Islam Salah said:
The JUnit framework never executes the code in the CallBack functions because the main thread of execution terminates before the response is retrieved.
You can use awaitility to solve the problem. Check out this answer on StackOverflow.

Categories

Resources