Thursday, 30 March 2017

Android: FileUriExposedException in Android N

If your android application shares files with/from other applications using Uri, and your application's targetSdkVersion is 24+ i.e Android N, then you may have encountered with an error/exception saying something like android.os.FileUriExposedException:

android.os.FileUriExposedException: file:///storage/emulated/0/DCIM/Camera/img_21032017190911.jpg exposed beyond app through ClipData.Item.getUri()

The error or exception is thrown when an application exposes a file:// Uri to another app.
Thus using file:// Uri is discouraged in this scenario because the receiving app may not have access to the path or the file:// Uri shared with it.
Like for example, the receiving app may not have requested the READ_EXTERNAL_STORAGE run time permission, or the platform may be sharing the file:// Uri across user profile boundaries, then this may result in an unexpected behaviour at best or at worst, it may result in a crash.

So the first thing to deal with this exception is that,

1. Your application should use content:// Uri instead of  file:// Uri so that the platform can extend temporary permission for the receiving app to access the resource.

2. Or you need to use FileProvider.

3. The work around from code can be done as follows:
    Just add the below code in your Application file's onCreate method as follows:

   public class ApplicationMain extends Application{

@Override
            public void onCreate() {
            super.onCreate();
....
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
....
}
   }


Note: This exception is only thrown for applications targeting N or higher. Applications targeting earlier SDK versions are allowed to share file:// Uri, but it's strongly discouraged.

That's all.
Share and comment if any issues.


Sunday, 26 March 2017

Android: Upload images using MultipartPost request

An HTTP MultipartPost request is a request that HTTP clients construct to send files and data over to a HTTP Server. It is commonly used by browsers and HTTP clients to upload files to the server.

To implement this request in your android applications to send images to your server follow these simple steps.

1. Add the following dependency in your build.gradle file:

                     compile 'com.squareup.okhttp3:okhttp:3.2.0'    

2. Now just add the code snippet with following parameters described as follows:


void uploadImageThroughMultipartPostRequest(File yourFileToBeUploaded) {

// yourFileToBeUploaded is your image file
        String contentType = null;
        RequestBody fileBody = null;
        if (yourFileToBeUploaded != null) {
            try {
                contentType = yourFileToBeUploaded.toURL().openConnection().getContentType();
            } catch (Exception e) {
                e.printStackTrace();
            }
            fileBody = RequestBody.create(MediaType.parse(contentType), yourFileToBeUploaded);
        }
       
       String requestURL = "YOUR_POST_REQUEST_URL" ;
       
       RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM) // Type to set Form request
                .addFormDataPart("uploaded_file", yourFileToBeUploaded.getPath())
                .addFormDataPart("uploaded_file_tag", "File_Name.jpeg", fileBody)
                .build();

        Request request = new Builder()
                .url(requestURL)
                .put(requestBody)
                .addHeader("Accept", "application/json")
                .addHeader("Content-Type", "application/json")
                .build();

        OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getActivity(), "Upload failure " + e.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                            Toast.makeText(getActivity(), "Message: "+response , Toast.LENGTH_SHORT).show();

                    }
                });
            }
        });
    }

3. Now just call the above method as follows:

            try {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            uploadImageThroughMultipartPostRequest(fileToUpload);
                        }
                    }).start();
                } catch (Exception ex) {
                    ex.getMessage();
                }

That's all.
Share and comment if any issues.


Thursday, 16 March 2017

Customizing Toast in Android

This post is regarding the customization of a Toast in your application.
You may have seen many a times some toast messages in android application notifying you that something has been completed or some action has been performed or executed.
These toast messages that you see are of the default representation from android but you can also customize your toast as you want.
This is quite simple which can be implemented as follows:

1. Create your xml layout file (custom_toast.xml) to show how your toast will look like.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="16dp"
            android:src="@drawable/sample_image" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="16dp"
            android:lines="2"
            android:text="This is your custom toast..!!!"
            android:textAlignment="center"
            android:textSize="12dp" />

    </LinearLayout>
</LinearLayout>

2. In your activity where you want to show the toast, just add the following snippet.

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = inflater.inflate(R.layout.custom_toast, null);
        Toast toast = new Toast(this);
        toast.setView(layout);
        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
        toast.show();

That's all. Here you go.
Share and comment if any issues.



Sunday, 5 March 2017

Android: Decoding a Base64 encoded string

Sometimes in your application you contain some data which is very useful to you or its so sensitive that you don't want anyone else to have it. In that you need to encode or encrypt your data while transferring it through your application.
So for encoding your data and use it in your android application, we have android.util.Base64 class which is used to encode/decode your data.
First of all encoding is not the same thing as encryption. If you’re storing or using useful and sensitive information, you should be encrypting, not simply Base64 encoding. But android.util.Base64 class is also a very useful tool for this purpose.
The use of this class is very simple as depicted in the below example:

1. First import the required class:

                         import android.util.Base64;

2. Now just use the below code: 

String str = "Hello, world!";
       
byte[] encodedStr = Base64.encode(str.getBytes(), Base64.DEFAULT);    
byte[] decodedStr = Base64.decode(encodedStr, Base64.DEFAULT);
       
Log.d("Android Castle", "Android Castle Default Value =  " + str);
Log.d("Android Castle", "Android Castle Encoded Value =  " + new String(encodedStr));
Log.d("Android Castle", "Android Castle Decoded Value =  " + new String(decodedStr));


3. The following will be out put of the above snippet:

Android Castle Default Value = Hello, world!
Android Castle Encoded Value  = SGVsbG8sIHdvcmxkIQ==
Android Castle Decoded Value = Hello, world!

But in many case we have some highly secure data where the data is encoded and then compressed and then its being transferred to your application. In that case being a developer you have to decode the data and decompress it as well to make it useful for your application. The solution for this problem is as follows:

1. Import as follows:

                    import  org.java_websocket.util.Base64;

2. Use the following code snippet:

            String st = "YOUR ENCODE STRING";

            byte[] decodedByte = new byte[0];
            byte[] result = new byte[0];
            int resultLength = 0;
            try {
                decodedByte = Base64.decode(st, Base64.GZIP);
                Inflater decompresser = new Inflater();
                decompresser.setInput(decodedByte, 0, decodedByte.length);
                result = new byte[decodedByte.length];
                resultLength = decompresser.inflate(result);
                decompresser.end();
                String outputString = new String(result, 0, resultLength, "UTF-8");
               
                System.out.println("Your decode string: " + outputString);

            } catch (Exception e) {
                e.printStackTrace();
            }

That's all.

Share and comment if any issues.