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.




Monday, 20 February 2017

Android ViewPager with page animation

In reference to my last post here, this post will show how to implement animation in your viewPager while sliding your pages in a very simple way with a few steps as follows:

1. Add a class that contains the page transformation code as follows:
In this class, the page slide animation is ZoomOutPage transformation which means that your new page will zoom out while you slide it to either side. You will be able to understand it more clearly once you implement it. So now add a class as follows:

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.85f;
        private static final float MIN_ALPHA = 0.5f;

        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();
            int pageHeight = view.getHeight();

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) { // [-1,1]
                // Modify the default slide transition to shrink the page as well
                float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
                float vertMargin = pageHeight * (1 - scaleFactor) / 2;
                float horzMargin = pageWidth * (1 - scaleFactor) / 2;
                if (position < 0) {
                    view.setTranslationX(horzMargin - vertMargin / 2);
                } else {
                    view.setTranslationX(-horzMargin + vertMargin / 2);
                }

                // Scale the page down (between MIN_SCALE and 1)
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

                // Fade the page relative to its size.
                view.setAlpha(MIN_ALPHA +
                        (scaleFactor - MIN_SCALE) /
                                (1 - MIN_SCALE) * (1 - MIN_ALPHA));

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }


2. Add another class that implements another page slide animation:
In this class, the page slide animation is ZoomInPage transformation which means that your new page will zoom in while you slide it to either side. First let's implement it and then see the changes.

    public class ZoomInPageTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.75f;

        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 0) { // [-1,0]
                // Use the default slide transition when moving to the left page
                view.setAlpha(1);
                view.setTranslationX(0);
                view.setScaleX(1);
                view.setScaleY(1);

            } else if (position <= 1) { // (0,1]
                // Fade the page out.
                view.setAlpha(1 - position);

                // Counteract the default slide transition
                view.setTranslationX(pageWidth * -position);

                // Scale the page down (between MIN_SCALE and 1)
                float scaleFactor = MIN_SCALE
                        + (1 - MIN_SCALE) * (1 - Math.abs(position));
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

3. Now just after the implementation of your viewPager in your class as stated in my previous post here, add the following line:

mPager = (ViewPager) findViewById(R.id.pager);
.......             ..............
mPager.setPageTransformer(true, new ZoomOutPageTransformer());
or
mPager.setPageTransformer(true, new ZoomInPageTransformer());

That's all. Now run your code and see how it works.

Comment if any issues.



Sunday, 12 February 2017

Android: Implementing ViewPager

This post is regarding the implementation of ViewPager in Android. ViewPager is basically the layout manager that allows you to flip(swipe) pages of data left or right or you can say with the help of ViewPager you can swipe left or right your view/screen containing some data.
ViewPager is most often used with Fragment, which is a convenient way to supply and manage the lifecycle of each page. There are standard adapters implemented for using fragments with the ViewPager, which cover the most common use cases. These are FragmentPagerAdapter and FragmentStatePagerAdapter; each of these classes have simple code showing how to build a full user interface with them.
Let's start the steps to implement a ViewPager:

-Create the Views
Create a layout file fragment_screen_slide_page.xml which will be used for the content of a fragment with the following snippet:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView style="?android:textAppearanceMedium"
        android:padding="16dp"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Your data to be displayed in your view." />
</ScrollView>


-Add a ViewPager
ViewPagers have built-in swipe gestures for transition through pages, and they display screen slide animations by default, so you don't need to create any. ViewPagers use PagerAdapters as a supply for new pages to display, so the PagerAdapter will use the fragment class that we created above.

Create a layout file activity_screen_slide.xml that contains a ViewPager:

<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

-Create an activity the does the following:
- Sets the content view to be the layout with the ViewPager.
- Creates a class that extends the FragmentStatePagerAdapter abstract class and implements the getItem() method to supply instances of ScreenSlidePageFragment as new pages. The pager adapter also requires that you implement the getCount() method, which returns the amount of pages the adapter will create (five in the example).
- Hooks up the PagerAdapter to the ViewPager.
- Handles the device's back button by moving backwards in the virtual stack of fragments. If the user is already on the first page, go back on the activity back stack.


import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
...
public class ScreenSlidePagerActivity extends FragmentActivity {

    private static final int NUM_PAGES = 5;
    private ViewPager mPager;
    private PagerAdapter mPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_slide);

        // Instantiate a ViewPager and a PagerAdapter.
        mPager = (ViewPager) findViewById(R.id.pager);
        mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
        mPager.setAdapter(mPagerAdapter);
    }

    @Override
    public void onBackPressed() {
        if (mPager.getCurrentItem() == 0) {
            // If the user is currently looking at the first step, allow the system to handle the
            // Back button. This calls finish() on this activity and pops the back stack.
            super.onBackPressed();
        } else {
            // Otherwise, select the previous step.
            mPager.setCurrentItem(mPager.getCurrentItem() - 1);
        }
    }

    /**
     * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
     * sequence.
     */
    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
        public ScreenSlidePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return new ScreenSlidePageFragment();
        }

        @Override
        public int getCount() {
            return NUM_PAGES;
        }
    }
}


-Create the Fragment
Create a Fragment class that returns the layout that you just created in the onCreateView() method. You can then create instances of this fragment in the parent activity whenever you need a new page to display to the user:

import android.support.v4.app.Fragment;
...
public class ScreenSlidePageFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup) inflater.inflate(
                R.layout.fragment_screen_slide_page, container, false);

        return rootView;
    }
}

That's all. You are done with ViewPager. Now run your app and swipe left or right to see changes in your data. You can customize the ViewPager according to your requirements as well.
I'll show you some hacks like page swipe animation in the ViewPager in my next post.




Thursday, 2 February 2017

Android Studio AVD issue in Ubuntu 16.10

As you all know Android Studio is the IDE used for developing android applications. Android Studio has a lot of built-in components and one of the most useful of them is your Android Virtual Device(AVD) Emulator. It helps you to test your applications in an easy way and without using a real device.
Now after downloading and setting up your Android Studio on your Ubuntu 16.10, you might face a problem saying something like:

Cannot launch AVD in emulator.
Output:
libGL error: unable to load driver: radeonsi_dri.so
libGL error: driver pointer missing
libGL error: unable to load driver: i965_dri.so
libGL error: driver pointer missing
libGL error: unable to load driver: r600_dri.so
libGL error: driver pointer missing
libGL error: unable to load driver: swrast_dri.so
libGL error: failed to load driver: swrast
X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  155 (GLX)
  Minor opcode of failed request:  24 (X_GLXCreateNewContext)
  Value in failed request:  0x0
  Serial number of failed request:  33
  Current serial number in output stream:  34

or may be saying: Unable to work with the Android Emulator.

This is basically a libGL error and libstdc++ issue.
It’s a known bug and you can easily fix it with some simple steps as follows:

1. First install some packages and libs:
    Type the following in your terminal

          $ sudo apt-get install lib64stdc++6:i386  

          $ sudo apt-get install mesa-utils  


2. Second, proceed with these commands:

         $ cd YOURPATH/Android/Sdk/tools/lib64  // In my case YOURPATH = /home/nishant  

         $ mv libstdc++/ libstdc++.bak  

         $ ln -s /usr/lib64/libstdc++.so.6  libstdc++  

3. Now relaunch your AVD device and test it.

That's all.
Its a tested solution for Ubuntu 16.10 64bit.

Comment if any issues.