Monday 20 January 2014

Android Storage system to access the path of External and Internal files and folders.


Android uses more than one file system (think of "multiple drives/partitions" when comparing with your computer, while sharing a common base, directory structures might differ between manufacturers.


What is a file system?

            A file system (or filesystem) is an abstraction to store, retrieve and update a set of files. The term also identifies the data structures specified by some of those abstractions, which are designed to organize multiple files as a single stream of bytes, and the network protocols specified by some other of those abstractions, which are designed to allow files on a remote machine to be accessed.


Android supports different file systems:
  • FAT: Used mainly for SDCards. This system is supported by most operating systems (Windows, Linux, Mac, etc.), which is why it's used for these "exchangeables". But it is also quite restricted, which is why it is rarely used somewhere else.
  • exFAT: sometimes used instead of FAT -- but not generally supported
  • extfs: The extended file system already has seen several generations. Android devices usually support ext2, ext3, and in most cases also ext4.
  • YAFFS: A Log structured file system designed for NAND flash, but also used with NOR flash. This was often used for e.g. the /data partition with many devices up to Android 2.x

There are also some pseudo-filesystems used on Unix/Linux system in general and on Android devices in special:
  • devfs: Virtual file system for managing devices on-the-fly
  • procfs: Pseudo-file system, used to access kernel information about processes
  • sysfs: Virtual file system holding information about buses, devices, firmware, filesystems, etc.


Internal storage of Android devices is devided into several partitions, each dedicated to a special "task". 

Some of the more important ones include:

/system: This is where the Android system and the pre-installed apps reside. It usually is mounted read-only, so on non-rooted devices you cannot write here (with the exception of applying a system update, e.g. OTA, or flashing a new ROM)

/data: Here the downloaded apps and all app's data are located. Additionally, some system settings are stored here, log files, and more

Your sdcard usually has a single partition only -- but also could be split into multiple partitions. 

Below are some of the ways i am showing you to access the various files and folders in android file system:

System directories
Method
Result
Environment.getDataDirectory()
/data
Environment.getDownloadCacheDirectory()
/cache
Environment.getRootDirectory()
/system
External storage directories
Method
Result
Environment.getExternalStorageDirectory()
/storage/sdcard0
Environment.getExternalStoragePublicDirectory(DIRECTORY_ALARMS)
/storage/sdcard0/Alarms
Environment.getExternalStoragePublicDirectory(DIRECTORY_DCIM)
/storage/sdcard0/DCIM
Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS)
/storage/sdcard0/Download
Environment.getExternalStoragePublicDirectory(DIRECTORY_MOVIES)
/storage/sdcard0/Movies
Environment.getExternalStoragePublicDirectory(DIRECTORY_MUSIC)
/storage/sdcard0/Music
Environment.getExternalStoragePublicDirectory(DIRECTORY_NOTIFICATIONS)
/storage/sdcard0/Notifications
Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES)
/storage/sdcard0/Pictures
Environment.getExternalStoragePublicDirectory(DIRECTORY_PODCASTS)
/storage/sdcard0/Podcasts
Environment.getExternalStoragePublicDirectory(DIRECTORY_RINGTONES)
/storage/sdcard0/Ringtones

Application directories
Method
Result
getCacheDir()
/data/data/package/cache
getFilesDir()
/data/data/package/files
getFilesDir().getParent()
/data/data/package
Application External storage directories
Method
Result
getExternalCacheDir()
/storage/sdcard0/Android/data/package/cache
getExternalFilesDir(null)
/storage/sdcard0/Android/data/package/files
getExternalFilesDir(DIRECTORY_ALARMS)
/storage/sdcard0/Android/data/package/files/Alarms
getExternalFilesDir(DIRECTORY_DCIM)
/storage/sdcard0/Android/data/package/files/DCIM
getExternalFilesDir(DIRECTORY_DOWNLOADS)
/storage/sdcard0/Android/data/package/files/Download
getExternalFilesDir(DIRECTORY_MOVIES)
/storage/sdcard0/Android/data/package/files/Movies
getExternalFilesDir(DIRECTORY_MUSIC)
/storage/sdcard0/Android/data/package/files/Music
getExternalFilesDir(DIRECTORY_NOTIFICATIONS)
/storage/sdcard0/Android/data/package/files/Notifications
getExternalFilesDir(DIRECTORY_PICTURES)
/storage/sdcard0/Android/data/package/files/Pictures
getExternalFilesDir(DIRECTORY_PODCASTS)
/storage/sdcard0/Android/data/package/files/Podcasts
getExternalFilesDir(DIRECTORY_RINGTONES)
/storage/sdcard0/Android/data/package/files/Ringtones


Thanks.

Wednesday 1 January 2014

Handle Scrolling of Scrollable Controls in Scrollview in Android

In life of any Android developer, there are times when there is a requirement in the application to use one scrollable control inside another scrollable control. In such cases, the scrolling functionality of one or all scrollable controls gets enabled and the Android application cannot identify that scroll event of which control is to be handled first. Here, UI may get stuck in some scenarios.
The ideal behavior expected is when the user touches the parent scroll view, only the parent view’s scroll event is called and when the user scrolls the child scroll view, the child view’s scroll event is called. In our standard Android application development and implementation process it does not happen when we add scrollable control in another scrollable control.
Below is the solution to handle the scroll event of both the controls without any glitch.
Example
We have a layout that has a ScrollView as parent layout and it contains some TextViews, ImageViews and ListView as child controls. As the below Layout:
 <ScrollView android:id=”@+id/parent_scroll” 
        android:layout_width=”fill_parent”
        android:layout_height=”wrap_content”
        android:layout_weight=”1″
        android:background=”@drawable/dotted_bg”
        android:focusableInTouchMode=”false”>
                    <LinearLayout   />
                    <LinearLayout   />
                    <LinearLayout  >
                    <ScrollView android:id=”@+id/child_scroll”  
                    android:layout_width=”fill_parent”
                    android:layout_height=”fill_parent”
                    android:background=”@drawable/text_box_bg”>
                <TextView android:id=”@+id/text_description”
                    android:layout_width=”fill_parent”
                    android:layout_height=”fill_parent”
                    android:textColor=”@color/gray”
                    android:textSize=”12dip”
                    android:padding=”5dip”
                    android:scrollbars=”vertical”/>
                <!–ScrollView>
              </LinearLayout>

Step 1 : Provide unique id to both the scrollview.
The id of the parent ScrollView is parent_scroll and child ScrollView is child_scroll. Now in the onCreate method we have to set Touchlistener event for both the scroll views and use requestDisallowInterceptTouchEvent of the view.
Step 2 : get reference of that two scrollview in your activity.
  parentScroll=(ScrollView)findViewById(R.id.parent_scroll);
    childScroll=(ScrollView)findViewById(R.id.child_scroll);
For parent scroll view, below code disables the scrolling event for the child scrollable controls in the parentScroll. So the user can scroll the parent scroll view and see the controls of parent scroll view without UI getting stuck.
 parentScroll.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                Log.v(TAG,”PARENT TOUCH”);
  findViewById(R.id.child_scroll).getParent().requestDisallowInterceptTouchEvent(false);
                return false;
            }
        });

For the child scroll view, below code disables the scroll event of parent scroll view if the user touches on child scroll view,

 childScroll.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) 
            {
                Log.v(TAG,”CHILD TOUCH”);
                // Disallow the touch request for parent scroll on touch of child view
                v.getParent().requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });

Note: According to the UI guide lines and best practices, it is advisable not to use Scrollable content inside Scrollview and doing that prevents the scrolling of the Scrollable content.
When you put two scrollview android just get confused which scroll view is touched. So sometimes it gets unable to deliver touch event.
But if still you want to achieve the scrolling functionality you can manage it by using the onTouch event of the particular view. And you need to design your layout accordingly.
But even if the requirement forces you to make such layouts. You can try as above.

Instagram API Integration in Android Application

OVERVIEW:

Instagram is a new but successful player in social domain nowadays. Instagram is a social networking service that allows its users to capture photos, modify and share them.
Instagram integration process is quite similar as Twitter integration. But for twitter we have tons of third party libraries, which we don’t have in case of Instagram.

In this blog you’ll see how to get authentication done in your app by using Instagram credentials.
  • Is there a way to get back our photos posted on instagram in our Android device?
             Yes, there is, Instagram provides an API to get the photos of the logged in user. So I started searching for this and got many links but did not get exact & clear steps from start to end implementation of this feature. So, I collected all the information and created a demo app for getting images from instagram and thought to put all my experience on paper so it is easy for Android developers reading this article to integrate it.

Below are the steps of how to implement this feature in android application using instagram API to get images from instagram account.

Integration Steps:

Step 1. Register a new client on Instagram

1. To create an application using the Instagram API you must have an account with   Instagram. Open Instagram Developer Website.
2. After creating an account with Instagram or logging into your existing account, open the Instagram Developer Website.
3. Click on the “Register Your Application” button and click on the “Register a New Client” button.




4. Enter the required details and press the register button, it will show some details like Client ID, Client Secret etc. Save all the details in the Constants file of the application.




Step 2. Authenticate.

         Once the Authentication is completed successfully you’ll get an Access Token that is required to make further request to the Instagram. 
There are two ways you can get an Access Token from Instagram.
  • Server Side Flow (Explicit)
  • Client Side Flow (Implicit)
In our case we'll go for the Server Side Flow(Explicit) because when we authenticate our app using implicit method we need to only get the Access Token to get the user information. We need to make a new request  to instagram. But if we follow the Implicit flow we'll receive lots of information related to the user, its username ,id etc.

         1. Save your client id and client secret in your strings.xml so we can access it in our code. You can make a constant class as well to store it inside your app. It is totally up to you where you want to save it. In my case I saved it in my strings.xml.

         2. Important URLs,

Note:MAKE SURE YOUR CALLBACK URL IS EXACTLY THE SAME AS YOU REGISTERED OTHERWISE THE INSTAGRAM WOULD SEND YOU AN ERROR RESPONSE.


     3. Form meaningful URLs using above URLs

              authURLString = AUTHURL + "?client_id=" + client_id + "&redirect_uri=" + CALLBACKURL + "&response_type=code&display=touch&scope=likes+comments+relationships";
             tokenURLString = TOKENURL + "?client_id=" + client_id + "&client_secret=" + client_secret + "&redirect_uri=" + CALLBACKURL + "&grant_type=authorization_code";


        There are four things to be noticed in the url created above:
  • client id :- This is the id which we got after registering the application
  • callback url :- The callbackurl which we have provided while registering the application
  • response_type :- This variable has 2 values, code and token. As we are using the Explicit(Server side) flow, we will use the “response_type=code”
  • scope :- This variable specifies the scope of access or permission for user data.
      4. Display the authURLString in a WebView or a Browser for user to authenticate
 WebView webView = new WebView(getContext());  
 webView.setVerticalScrollBarEnabled(false);  
 webView.setHorizontalScrollBarEnabled(false);  
 webView.setWebViewClient(new AuthWebViewClient());   
 webView.getSettings().setJavaScriptEnabled(true);  
 webView.loadUrl(authURLString);  
     
       5. Now create a class that extends the WebViewClient class to handle the response sent back by Instagram. We will use the shouldOverrideUrlLoading method of the WebviewClient to get the access token from Instagram.
  public class AuthWebViewClient extends WebViewClient  
   {  
    @Override  
     public boolean shouldOverrideUrlLoading(WebView view, String url)   
  {  
   if (url.startsWith(CALLBACKURL))   
   {   
      System.out.println(url);  
      String parts[] = url.split("=");  
      request_token = parts[1]; //This is your request token.  
      InstagramLoginDialog.this.dismiss();  
   return true;  
       }  
  return false;  
        }  
   }  

Step 3. Request Instagram Server to get the Access token.

1. Create a class that extends Asynctask and put the code given below in the   doInBackground() method.

2. The code opens an HTTPS connection and provides necessary details to Instagram server and then gets the Access token. After you get the access token, Store it in a variable or Shared preferences.

 try  
 {  
     URL url = new URL(tokenURLString);  
     HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();  
     httpsURLConnection.setRequestMethod("POST");  
     httpsURLConnection.setDoInput(true);  
     httpsURLConnection.setDoOutput(true);  
     OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpsURLConnection.getOutputStream());  
     outputStreamWriter.write("client_id="+client_id+  
                     "client_secret="+ client_secret +  
                     "grant_type=authorization_code" +  
                     "redirect_uri="+CALLBACKURL+  
                     "code=" + token);  
     outputStreamWriter.flush();  
     String response = streamToString(httpsURLConnection.getInputStream());  
     JSONObject jsonObject = (JSONObject) new JSONTokener(response).nextValue();  
     accessTokenString = jsonObject.getString("access_token"); //Here is your ACCESS TOKEN  
     id = jsonObject.getJSONObject("user").getString("id");  
     username = jsonObject.getJSONObject("user").getString("username");   
     //This is how you can get the user info.   
     //You can explore the JSON sent by Instagram as well to know what info you got in a response  
 }catch (Exception e)  
 {  
    e.printStackTrace();  
 }  

Step 4. Get the information of the user.
    1. We need to form an endpoint URL to hit the server for photos request
 String urlString = APIURL + "/users/"+ {User's Instagram Id} +"/media/recent/?access_token=" + {Instagram Access Token};  
  URL url = new URL(urlString);  

There are two things to notice in above urlString: – 
              Instagram Id and Access Token. 
              We already have got Instagram Access token and User Id 

2. Now open a connection and get the input stream from the url. You need to convert the input stream into a string before starting using it.
 InputStream inputStream = url.openConnection().getInputStream();  
 String response = instagramImpl.streamToString(inputStream);  

3. The streamToString() method is explained in the code given below
    /**  
   * Method that returns String from the InputStream given by p_is   
   * @param p_is The given InputStream  
  * @return The String from the InputStream  
  */  
  public static String streamToString(InputStream p_is)  
  {  
   try  
   {  
     BufferedReader m_br;  
      StringBuffer m_outString = new StringBuffer();  
      m_br = new BufferedReader(new InputStreamReader(p_is));  
      String m_read = m_br.readLine();  
      while(m_read != null)  
      {  
       m_outString.append(m_read);  
       m_read =m_br.readLine();//Use for loop to traverse through the JsonArray.
JSONObject mainImageJsonObject = jsonArray.getJSONObject(index).getJSONObject("images").getJSONObject("low_resolution");String imageUrlString = imageJsonObject.getString("url");  
      }  
     return m_outString.toString();  
   }  
  catch (Exception e)  
   {  
        e.printStackTrace();  
      }  
  }  

Instagram sends response in the form of Json so we need to convert the response into Json.
 JSONObject jsonObject = (JSONObject) new JSONTokener(response).nextValue();  
 JSONArray jsonArray = jsonObject.getJSONArray("data");  

And below is the code to get the image url: -
 //Use for loop to traverse through the JsonArray.  
 JSONObject mainImageJsonObject = jsonArray.getJSONObject(index).getJSONObject("images").getJSONObject("low_resolution");  
 String imageUrlString = imageJsonObject.getString("url");  

Instagram saves images in three different size on its server so we have three options to choose from,
  • Standard Resolution – standard_resolution
  • Low Resolution – low_resolution
  • Thumbnail – thumbnail
4.We can also get more details from the json string and we can use it get the details of the user/images and use it in our application.
5. For more methods of API please check: APIConsole

After getting the urls for the images, we can display the images in our application as per our need. We can also get the other details about the image.