Getting started with AndroidLayoutsGradle for AndroidRecyclerView onClickListenersNavigationViewIntentJSON in Android with org.jsonAndroid StudioResourcesData Binding LibraryExceptionsGetting Calculated View DimensionsAsyncTaskSharedPreferencesEmulatorMaterial DesignLint WarningsServiceStoring Files in Internal & External StorageWebViewProject SDK versionsRecyclerViewGoogle Maps API v2 for AndroidPorterDuff Mode9-Patch ImagesAndroid NDKRecyclerView DecorationsCamera 2 APIViewPagerCardViewHttpURLConnectionSQLiteADB (Android Debug Bridge)ButterKnifeSupporting Screens With Different Resolutions, SizesGlideRetrofit2DialogACRAGreenDAOFormatting StringsNotificationsAlarmManagerFragmentsHandlerCreating Custom ViewsBroadcastReceiverActivitySnackbarRuntime Permissions in API-23 +Logging and using LogcatVectorDrawable and AnimatedVectorDrawableTools AttributesToastInterfacesAnimatorsLocationTheme, Style, AttributeThe Manifest FileParcelableMediaPlayerMultidex and the Dex Method LimitData Synchronization with Sync AdapterMenuInstant Run in Android StudioPicassoBluetooth and Bluetooth LE APIRoboGuiceMemory LeaksUniversal Image LoaderVolleyWidgetsDate and Time PickersIntegrate Google Sign InIn-app BillingFloatingActionButtonContentProviderDagger 2RealmUnit testing in Android with JUnitAndroid VersionsWi-Fi ConnectionsSensorManagerLocalization with resources in AndroidProgressBarCustom FontsVibrationGoogle Awareness APIsText to Speech(TTS)UI LifecycleSpinnerData Encryption/DecryptionTesting UI with EspressoWriting UI tests - AndroidGreenRobot EventBusOkHttpEnhancing Android Performance Using Icon FontsHandling Deep LinksCanvas drawing using SurfaceViewFirebaseCrash Reporting ToolsCheck Internet ConnectivityFacebook SDK for AndroidUnzip File in AndroidAndroid Places APICreating your own libraries for Android applicationsGsonDevice Display MetricsTextViewListViewBuilding Backwards Compatible AppsLoaderProGuard - Obfuscating and Shrinking your codeDetect Shake Event in AndroidTypedef Annotations: @IntDef, @StringDefCapturing ScreenshotsMVP ArchitectureOrientation ChangesXposedSecurityPackageManagerImageViewGesture DetectionDoze ModeAndroid Sound and MediaSearchViewCamera and GalleryCallback URLTwitter APIsDrawablesColorsConstraintLayoutRenderScriptFrescoSwipe to RefreshAutoCompleteTextViewInstalling apps with ADBIntentServiceAdMobImplicit IntentsPublish to Play StoreFirebase Realtime DataBaseImage CompressionEmail ValidationKeyboardButtonTextInputLayoutBottom SheetsCoordinatorLayout and BehaviorsEditTextAndroid Paypal Gateway IntegrationFirebase App IndexingFirebase Crash ReportingDisplaying Google AdsAndroid Vk SdkLocalized Date/Time in AndroidCount Down TimerBarcode and QR code readingOtto Event BusTransitionDrawablePort Mapping using Cling library in AndroidCreating Overlay (always-on-top) WindowsExoPlayerInter-app UI testing with UIAutomatorMediaSessionSpeech to Text ConversionFileProviderPublish .aar file to Apache Archiva with GradleXMPP register login and chat simple exampleAndroid AuthenticatorRecyclerView and LayoutManagersAudioManagerJob SchedulingAccounts and AccountManagerIntegrate OpenCV into Android StudioSplit Screen / Multi-Screen ActivitiesThreadMediaStoreTime UtilsTouch EventsFingerprint API in androidMVVM (Architecture)BottomNavigationViewORMLite in androidYoutube-APITabLayoutRetrofit2 with RxJavaDayNight Theme (AppCompat v23.2 / API 14+)ShortcutManagerLruCacheJenkins CI setup for Android ProjectsZip file in androidVector DrawablesfastlaneDefine step value (increment) for custom RangeSeekBarGetting started with OpenGL ES 2.0+Check Data ConnectionAndroid Java Native Interface (JNI)FileIO with AndroidPerformance OptimizationRobolectricMoshiStrict Mode Policy : A tool to catch the bug in the Compile Time.Internationalization and localization (I18N and L10N)Fast way to setup Retrolambda on an android project.How to use SparseArrayFirebase Cloud MessagingShared Element TransitionsAndroid ThingsVideoViewViewFlipperLibrary Dagger 2: Dependency Injection in ApplicationsFormatting phone numbers with pattern.How to store passwords securelyAndroid Kernel OptimizationPaintAudioTrackWhat is ProGuard? What is use in Android?Create Android Custom ROMsJava on AndroidPagination in RecyclerViewGenymotion for androidHandling touch and motion eventsCreating Splash screenConstraintSetCleverTapPublish a library to Maven Repositoriesadb shellPing ICMPAIDLAndroid programming with KotlinAutosizing TextViewsSign your Android App for ReleaseContextActivity RecognitionSecure SharedPreferencesSecure SharedPreferencesBitmap CacheAndroid-x86 in VirtualBoxJCodecDesign PatternsOkioGoogle signin integration on androidTensorFlowAndroid game developmentNotification Channel Android OBluetooth Low EnergyLeakcanaryAdding a FuseView to an Android ProjectAccessing SQLite databases using the ContentValues classEnhancing Alert DialogsHardware Button Events/Intents (PTT, LWP, etc.)SpannableStringLooperOptimized VideoViewGoogle Drive APIAnimated AlertDialog BoxAnnotation ProcessorSyncAdapter with periodically do sync of dataCreate Singleton Class for Toast MessageFastjsonAndroid Architecture ComponentsJacksonGoogle Play StoreLoading Bitmaps EffectivelyGetting system font names and using the fontsSmartcardConvert vietnamese string to english string Android

Retrofit2

Other topics

Remarks:

Dependencies for the retrofit library:

From the official documentation:

Gradle:

dependencies {
    ...
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'    
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    ...
}

Maven:

<dependency>
  <groupId>com.squareup.retrofit2</groupId>
  <artifactId>retrofit</artifactId>
  <version>2.3.0</version>
</dependency>

A Simple GET Request

We are going to be showing how to make a GET request to an API that responds with a JSON object or a JSON array. The first thing we need to do is add the Retrofit and GSON Converter dependencies to our module's gradle file.

Add the dependencies for retrofit library as described in the Remarks section.

Example of expected JSON object:

{
    "deviceId": "56V56C14SF5B4SF",
    "name": "Steven",
    "eventCount": 0
}

Example of JSON array:

[
    {
        "deviceId": "56V56C14SF5B4SF",
        "name": "Steven",
        "eventCount": 0
    },
    {
        "deviceId": "35A80SF3QDV7M9F",
        "name": "John",
        "eventCount": 2
    }
]

Example of corresponding model class:

public class Device
{
    @SerializedName("deviceId")
    public String id;

    @SerializedName("name")
    public String name;

    @SerializedName("eventCount")
    public int eventCount;
}

The @SerializedName annotations here are from the GSON library and allows us to serialize and deserialize this class to JSON using the serialized name as the keys. Now we can build the interface for the API that will actually fetch the data from the server.

public interface DeviceAPI
{
    @GET("device/{deviceId}")
    Call<Device> getDevice (@Path("deviceId") String deviceID);

    @GET("devices")
    Call<List<Device>> getDevices();
}

There's a lot going on here in a pretty compact space so let's break it down:

  • The @GET annotation comes from Retrofit and tells the library that we're defining a GET request.
  • The path in the parentheses is the endpoint that our GET request should hit (we'll set the base url a little later).
  • The curly-brackets allow us to replace parts of the path at run time so we can pass arguments.
  • The function we're defining is called getDevice and takes the device id we want as an argument.
  • The @PATH annotation tells Retrofit that this argument should replace the "deviceId" placeholder in the path.
  • The function returns a Call object of type Device.

Creating a wrapper class:

Now we will make a little wrapper class for our API to keep the Retrofit initialization code wrapped up nicely.

public class DeviceAPIHelper
{
    public final DeviceAPI api;

    private DeviceAPIHelper ()
    {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://example.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        api = retrofit.create(DeviceAPI.class);
    }
}

This class creates a GSON instance to be able to parse the JSON response, creates a Retrofit instance with our base url and a GSONConverter and then creates an instance of our API.

Calling the API:

// Getting a JSON object
Call<Device> callObject = api.getDevice(deviceID);
callObject.enqueue(new Callback<Response<Device>>()
{
    @Override
    public void onResponse (Call<Device> call, Response<Device> response)
    {
        if (response.isSuccessful()) 
        {
           Device device = response.body();
        }
    }

    @Override
    public void onFailure (Call<Device> call, Throwable t)
    {
        Log.e(TAG, t.getLocalizedMessage());
    }
});

// Getting a JSON array
Call<List<Device>> callArray = api.getDevices();
callArray.enqueue(new Callback<Response<List<Device>>()
{
    @Override
    public void onResponse (Call<List<Device>> call, Response<List<Device>> response)
    {
        if (response.isSuccessful()) 
        {
           List<Device> devices = response.body();
        }
    }

    @Override
    public void onFailure (Call<List<Device>> call, Throwable t)
    {
        Log.e(TAG, t.getLocalizedMessage());
    }
});

This uses our API interface to create a Call<Device> object and to create a Call<List<Device>> respectively. Calling enqueue tells Retrofit to make that call on a background thread and return the result to the callback that we're creating here.

Note: Parsing a JSON array of primitive objects (like String, Integer, Boolean, and Double) is similar to parsing a JSON array. However, you don't need your own model class. You can get the array of Strings for example by having the return type of the call as Call<List<String>>.

Add logging to Retrofit2

Retrofit requests can be logged using an intercepter. There are several levels of detail available: NONE, BASIC, HEADERS, BODY. See Github project here.

  1. Add dependency to build.gradle:
compile 'com.squareup.okhttp3:logging-interceptor:3.8.1'
  1. Add logging interceptor when creating Retrofit:
  HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
  loggingInterceptor.setLevel(LoggingInterceptor.Level.BODY);
  OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
          .addInterceptor(loggingInterceptor)
          .build();
  Retrofit retrofit = new Retrofit.Builder()
          .baseUrl("http://example.com/")
          .client(okHttpClient)
          .addConverterFactory(GsonConverterFactory.create(gson))
          .build();

Exposing the logs in the Terminal(Android Monitor) is something that should be avoided in the release version as it may lead to unwanted exposing of critical information such as Auth Tokens etc.

To avoid the logs being exposed in the run time, check the following condition

if(BuildConfig.DEBUG){
     //your interfector code here   
    }

For example:

HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
if(BuildConfig.DEBUG){
     //print the logs in this case   
    loggingInterceptor.setLevel(LoggingInterceptor.Level.BODY);
}else{
    loggingInterceptor.setLevel(LoggingInterceptor.Level.NONE);
}

OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
      .addInterceptor(loggingInterceptor)
      .build();

Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://example.com/")
      .client(okHttpClient)
      .addConverterFactory(GsonConverterFactory.create(gson))
      .build();

Uploading a file via Multipart

Declare your interface with Retrofit2 annotations:

public interface BackendApiClient {
    @Multipart
    @POST("/uploadFile")
    Call<RestApiDefaultResponse> uploadPhoto(@Part("file\"; filename=\"photo.jpg\" ") RequestBody photo);
}

Where RestApiDefaultResponse is a custom class containing the response.

Building the implementation of your API and enqueue the call:

Retrofit retrofit = new Retrofit.Builder()
                                .addConverterFactory(GsonConverterFactory.create())
                                .baseUrl("http://<yourhost>/")
                                .client(okHttpClient)
                                .build();

BackendApiClient apiClient = retrofit.create(BackendApiClient.class);
RequestBody reqBody = RequestBody.create(MediaType.parse("image/jpeg"), photoFile);
Call<RestApiDefaultResponse> call = apiClient.uploadPhoto(reqBody);
call.enqueue(<your callback function>);

Retrofit with OkHttp interceptor

This example shows how to use a request interceptor with OkHttp. This has numerous use cases such as:

  • Adding universal header to the request. E.g. authenticating a request
  • Debugging networked applications
  • Retrieving raw response
  • Logging network transaction etc.
  • Set custom user agent
Retrofit.Builder builder = new Retrofit.Builder()
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl("https://api.github.com/");

if (!TextUtils.isEmpty(githubToken)) {
    // `githubToken`: Access token for GitHub
    OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
        @Override public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Request newReq = request.newBuilder()
                    .addHeader("Authorization", format("token %s", githubToken))
                    .build();
            return chain.proceed(newReq);
        }
    }).build();

    builder.client(client);
}

return builder.build().create(GithubApi.class);

See OkHttp topic for more details.

Header and Body: an Authentication Example

The @Header and @Body annotations can be placed into the method signatures and Retrofit will automatically create them based on your models.

public interface MyService {
     @POST("authentication/user")
     Call<AuthenticationResponse> authenticateUser(@Body AuthenticationRequest request, @Header("Authorization") String basicToken);
}

AuthenticaionRequest is our model, a POJO, containing the information the server requires. For this example, our server wants the client key and secret.

public class AuthenticationRequest {
     String clientKey;
     String clientSecret;
}

Notice that in @Header("Authorization") we are specifying we are populating the Authorization header. The other headers will be populated automatically since Retrofit can infer what they are based on the type of objects we are sending and expecting in return.

We create our Retrofit service somewhere. We make sure to use HTTPS.

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https:// some example site")
            .client(client)
            .build();
MyService myService = retrofit.create(MyService.class)

Then we can use our service.

AuthenticationRequest request = new AuthenticationRequest();
request.setClientKey(getClientKey());
request.setClientSecret(getClientSecret());
String basicToken = "Basic " + token;
myService.authenticateUser(request, basicToken);

Upload multiple file using Retrofit as multipart

Once you have setup the Retrofit environment in your project, you can use the following example that demonstrates how to upload multiple files using Retrofit:

private void mulipleFileUploadFile(Uri[] fileUri) {
    OkHttpClient okHttpClient = new OkHttpClient();
    OkHttpClient clientWith30sTimeout = okHttpClient.newBuilder()
            .readTimeout(30, TimeUnit.SECONDS)
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(API_URL_BASE)
            .addConverterFactory(new MultiPartConverter())
            .client(clientWith30sTimeout)
            .build();

    WebAPIService service = retrofit.create(WebAPIService.class); //here is the interface which you have created for the call service
    Map<String, okhttp3.RequestBody> maps = new HashMap<>();

    if (fileUri!=null && fileUri.length>0) {
        for (int i = 0; i < fileUri.length; i++) {
            String filePath = getRealPathFromUri(fileUri[i]);
            File file1 = new File(filePath);

            if (filePath != null && filePath.length() > 0) {
                if (file1.exists()) {
                    okhttp3.RequestBody requestFile = okhttp3.RequestBody.create(okhttp3.MediaType.parse("multipart/form-data"), file1);
                    String filename = "imagePath" + i; //key for upload file like : imagePath0
                    maps.put(filename + "\"; filename=\"" + file1.getName(), requestFile);
                }
            }
        }
    }

    String descriptionString = " string request";//
    //hear is the your json request
    Call<String> call = service.postFile(maps, descriptionString);
    call.enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call,
                               Response<String> response) {
            Log.i(LOG_TAG, "success");
            Log.d("body==>", response.body().toString() + "");
            Log.d("isSuccessful==>", response.isSuccessful() + "");
            Log.d("message==>", response.message() + "");
            Log.d("raw==>", response.raw().toString() + "");
            Log.d("raw().networkResponse()", response.raw().networkResponse().toString() + "");
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            Log.e(LOG_TAG, t.getMessage());
        }
    });
}
    
public String getRealPathFromUri(final Uri uri) { // function for file path from uri,
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(mContext, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(mContext, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{
                    split[1]
            };

            return getDataColumn(mContext, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(mContext, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}

Following is the interface

public interface WebAPIService {
    @Multipart
    @POST("main.php")
    Call<String> postFile(@PartMap Map<String,RequestBody> Files, @Part("json") String description);
}

Download a file from Server using Retrofit2

Interface declaration for downloading a file

public interface ApiInterface {
    @GET("movie/now_playing")
    Call<MovieResponse> getNowPlayingMovies(@Query("api_key") String apiKey, @Query("page") int page);

    // option 1: a resource relative to your base URL
    @GET("resource/example.zip")
    Call<ResponseBody> downloadFileWithFixedUrl();

    // option 2: using a dynamic URL
    @GET
    Call<ResponseBody> downloadFileWithDynamicUrl(@Url String fileUrl);
}

The option 1 is used for downloading a file from Server which is having fixed URL. and option 2 is used to pass a dynamic value as full URL to request call. This can be helpful when downloading files, which are dependent of parameters like user or time.

Setup retrofit for making api calls

public class ServiceGenerator {

    public static final String API_BASE_URL = "http://your.api-base.url/";

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
            .baseUrl(API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass){
        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(serviceClass);
    }

}

Now, make implementation of api for downloading file from server

private void downloadFile(){
        ApiInterface apiInterface = ServiceGenerator.createService(ApiInterface.class);

        Call<ResponseBody> call = apiInterface.downloadFileWithFixedUrl();

        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (response.isSuccessful()){
                    boolean writtenToDisk = writeResponseBodyToDisk(response.body());

                    Log.d("File download was a success? ", String.valueOf(writtenToDisk));
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });
    }

And after getting response in the callback, code some standard IO for saving file to disk. Here is the code:

private boolean writeResponseBodyToDisk(ResponseBody body) {
        try {
            // todo change the file location/name according to your needs
            File futureStudioIconFile = new File(getExternalFilesDir(null) + File.separator + "Future Studio Icon.png");

            InputStream inputStream = null;
            OutputStream outputStream = null;

            try {
                byte[] fileReader = new byte[4096];

                long fileSize = body.contentLength();
                long fileSizeDownloaded = 0;

                inputStream = body.byteStream();
                outputStream = new FileOutputStream(futureStudioIconFile);

                while (true) {
                    int read = inputStream.read(fileReader);

                    if (read == -1) {
                        break;
                    }

                    outputStream.write(fileReader, 0, read);

                    fileSizeDownloaded += read;

                    Log.d("File Download: " , fileSizeDownloaded + " of " + fileSize);
                }

                outputStream.flush();

                return true;
            } catch (IOException e) {
                return false;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }

                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            return false;
        }
    }

Note we have specified ResponseBody as return type, otherwise Retrofit will try to parse and convert it, which doesn't make sense when you are downloading file.

If you want more on Retrofit stuffs, got to this link as it is very useful. [1]: https://futurestud.io/blog/retrofit-getting-started-and-android-client

Debugging with Stetho

Add the following dependencies to your application.

compile 'com.facebook.stetho:stetho:1.5.0' 
compile 'com.facebook.stetho:stetho-okhttp3:1.5.0' 

In your Application class' onCreate method, call the following.

Stetho.initializeWithDefaults(this);

When creating your Retrofit instance, create a custom OkHttp instance.

OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
clientBuilder.addNetworkInterceptor(new StethoInterceptor());

Then set this custom OkHttp instance in the Retrofit instance.

Retrofit retrofit = new Retrofit.Builder()
    // ...
    .client(clientBuilder.build())
    .build();

Now connect your phone to your computer, launch the app, and type chrome://inspect into your Chrome browser. Retrofit network calls should now show up for you to inspect.

Retrofit 2 Custom Xml Converter

Adding dependencies into the build.gradle file.

dependencies {
    ....
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile ('com.thoughtworks.xstream:xstream:1.4.7') {
        exclude group: 'xmlpull', module: 'xmlpull'
    }
    ....
}

Then create Converter Factory

public class XStreamXmlConverterFactory extends Converter.Factory {

    /** Create an instance using a default {@link com.thoughtworks.xstream.XStream} instance for conversion. */
    public static XStreamXmlConverterFactory create() {
        return create(new XStream());
    }

    /** Create an instance using {@code xStream} for conversion. */
    public static XStreamXmlConverterFactory create(XStream xStream) {
        return new XStreamXmlConverterFactory(xStream);
    }

    private final XStream xStream;

    private XStreamXmlConverterFactory(XStream xStream) {
        if (xStream == null) throw new NullPointerException("xStream == null");
        this.xStream = xStream;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {

        if (!(type instanceof Class)) {
            return null;
        }

        Class<?> cls = (Class<?>) type;

        return new XStreamXmlResponseBodyConverter<>(cls, xStream);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {

        if (!(type instanceof Class)) {
            return null;
        }

        return new XStreamXmlRequestBodyConverter<>(xStream);
    }
}

create a class to handle the body request.

final class XStreamXmlResponseBodyConverter <T> implements Converter<ResponseBody, T> {

    private final Class<T> cls;
    private final XStream xStream;

    XStreamXmlResponseBodyConverter(Class<T> cls, XStream xStream) {
        this.cls = cls;
        this.xStream = xStream;
    }

    @Override
    public T convert(ResponseBody value) throws IOException {

        try {

            this.xStream.processAnnotations(cls);
            Object object =  this.xStream.fromXML(value.byteStream());
            return (T) object;

        }finally {
            value.close();
        }
    }
}

create a class to handle the body response.

final class XStreamXmlRequestBodyConverter<T> implements Converter<T, RequestBody> {

    private static final MediaType MEDIA_TYPE = MediaType.parse("application/xml; charset=UTF-8");
    private static final String CHARSET = "UTF-8";

    private final XStream xStream;

    XStreamXmlRequestBodyConverter(XStream xStream) {
        this.xStream = xStream;
    }

    @Override
    public RequestBody convert(T value) throws IOException {

        Buffer buffer = new Buffer();

        try {
            OutputStreamWriter osw = new OutputStreamWriter(buffer.outputStream(), CHARSET);
            xStream.toXML(value, osw);
            osw.flush();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}

So, this point we can send and receive any XML , We just need create XStream Annotations for the entities.

Then create a Retrofit instance:

XStream xs = new XStream(new DomDriver());
xs.autodetectAnnotations(true);

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://example.com/")
    .addConverterFactory(XStreamXmlConverterFactory.create(xs))
    .client(client)
    .build();

A simple POST request with GSON

Sample JSON:

{ 
    "id": "12345",
    "type": "android"
}

Define your request:

public class GetDeviceRequest {

    @SerializedName("deviceId")
    private String mDeviceId;

    public GetDeviceRequest(String deviceId) {
        this.mDeviceId = deviceId;
    }

    public String getDeviceId() {
        return mDeviceId;
    }

}

Define your service (endpoints to hit):

public interface Service {

    @POST("device")
    Call<Device> getDevice(@Body GetDeviceRequest getDeviceRequest);

}

Define your singleton instance of the network client:

public class RestClient {

    private static Service REST_CLIENT;

    static {
        setupRestClient();
    }

    private static void setupRestClient() {
        
        // Define gson 
        Gson gson = new Gson();

        // Define our client 
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://example.com/")
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

        REST_CLIENT = retrofit.create(Service.class);
    }

    public static Retrofit getRestClient() {
        return REST_CLIENT;
    }

} 

Define a simple model object for the device:

public class Device {

    @SerializedName("id")
    private String mId;

    @SerializedName("type")
    private String mType;

    public String getId() {
        return mId;
    }

    public String getType() {
        return mType;
    }

}

Define controller to handle the requests for the device

public class DeviceController {

    // Other initialization code here...

    public void getDeviceFromAPI() {

        // Define our request and enqueue 
        Call<Device> call = RestClient.getRestClient().getDevice(new GetDeviceRequest("12345"));

        // Go ahead and enqueue the request 
        call.enqueue(new Callback<Device>() {
            @Override
            public void onSuccess(Response<Device> deviceResponse) {
                // Take care of your device here 
                if (deviceResponse.isSuccess()) {
                    // Handle success
                    //delegate.passDeviceObject();
                }
            }

            @Override
            public void onFailure(Throwable t) {
                // Go ahead and handle the error here 
            } 

        });

Reading XML form URL with Retrofit 2

We will use retrofit 2 and SimpleXmlConverter to get xml data from url and parse to Java class.

Add dependency to Gradle script:

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-simplexml:2.1.0'

Create interface

Also create xml class wrapper in our case Rss class

    public interface ApiDataInterface{
    
        // path to xml link on web site
    
        @GET (data/read.xml)
    
        Call<Rss> getData();

}

Xml read function

private void readXmlFeed() {
        try {

            // base url - url of web site
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(http://www.google.com/)
                    .client(new OkHttpClient())
                    .addConverterFactory(SimpleXmlConverterFactory.create())
                    .build();

            ApiDataInterface apiService = retrofit.create(ApiDataInterface.class);

            Call<Rss> call = apiService.getData();
            call.enqueue(new Callback<Rss>() {

                @Override
                public void onResponse(Call<Rss> call, Response<Rss> response) {

                    Log.e("Response success", response.message());
                    
                }

                @Override
                public void onFailure(Call<Rss> call, Throwable t) {
                    Log.e("Response fail", t.getMessage());
                }
            });

        } catch (Exception e) {
            Log.e("Exception", e.getMessage());
        }


    }

This is example of Java class with SimpleXML annotations

More about annotations SimpleXmlDocumentation

@Root (name = "rss")

public class Rss
{


    public Rss() {

    }



    public Rss(String title, String description, String link, List<Item> item, String language) {

        this.title = title;
        this.description = description;
        this.link = link;
        this.item = item;
        this.language = language;

    }

    @Element (name = "title")
    private String title;

    @Element(name = "description")
    private String description;

    @Element(name = "link")
    private String link;

    @ElementList (entry="item", inline=true)
    private List<Item> item;

    @Element(name = "language")
    private String language;

Contributors

Topic Id: 1132

Example Ids: 3651,4599,7695,9327,10992,14534,14961,16388,18965,20602,26230

This site is not affiliated with any of the contributors.