Android : Write app directory without worrying anything

TL;DR : this

Almost all of us who has developed in android for decent amount of time has faced a situation where we have to export a data of our application to a file in sd-card (or better say technically external storage). And I bet too many people faced the challenge to make this thing working in every device. Sometimes (y)our app is writing a file where there is no external storage, some times we use hard-coded path, because at some point of history, sd cards were mounted on that path and all devices follow this ritual. At some point of time the external storage is not available for us to write a file because of various reasons. And after crossing all these hurdles, we want to save all our app-created files in directory named after our app. For better organization and/or for any kind of branding purpose.

Many of us faced this problem, many of us are facing this right now. I have faced this issue too. This is a general operation that we have done n times and will do n+n times. What if there is a kind of plugin or library developed for this, That automates all the process, without worrying little details and with giving us proper errors whenever we face?

That’s where AppExternalFileWriter comes into the picture. I am talking about a class I have recently developed that (I believe) mostly automates the process said above. Doing some things automatically, as well let us(the programmers) do some extra cherry-picking at will.

Interested? Want to use? If not, you are not forced to read anything after this line. If yes, these are the droids you are looking for.

First of all, let me tell you how to work with the class.

1. Create an object of AppExternalFileWriter, to do that you need a Context object to pass to.

2. If you want to create a subfolder use suitable createSubDirectory variants.

3. use writeDataToFile or writeDataToTimeStampedFile variants as per your wish.

4. If you want to write a data where a file name should be a time stamp use writeDataToTimeStampedFile variants.

5. Apart from all I nearly forgot to add that, If anything is wrong with external storage, like storage not mounted, corrupt,  shared as mass storage, not enough space available, or even trying to create a library already created. The class will throw ExternalFileWriterException with the message stating what happened. Thus giving you the power to handle some crappy situations.

Here are some important variants you may want to use.

  1. writeDataToFile – Without parent directories
    writeDataToFile(String fileName, byte[] data);
    writeDataToFile(String fileName, String data);

    Writes data to desired file in Application directory.

  2. writeDataToFile – With parent directories
    writeDataToFile(File parent, String fileName, byte[] data);
    writeDataToFile(File parent, String fileName, String data);

    Writes data to desired file in other directory.

  3. writeDataToTimeStampedFile variants – Without parent directories
    writeDataToTimeStampedFile(String extension, byte[] data)
    writeDataToTimeStampedFile(String extension, String data)

    Writes data to desired file with timestamp with extension in Application directory.

  4. writeDataToTimeStampedFile variants – With parent directories
    writeDataToTimeStampedFile(String extension, byte[] data)
    writeDataToTimeStampedFile(String extension, String data)

    Writes data to desired file with timestamp with extension in other directory.

  5. createSubDirectory variants
    createSubDirectory(File parent, String directoryName)

    Creates subdirectory in application directory

    createSubDirectory(String directoryName)

    Creates subdirectory in any other directory

some other useful methods

  1. getAppDirectory()

    get File object of created app directory

  2. getExternalStorageDirectory()

    get File object of external storage directory

The full code with Sample is shared at this repository, fork and use it at your will.

May the force be with you.

Advertisements

The Android Studio Story 2: When the life begins.

So In the first part we have met our new friend Android Studio and knew a little bit about it. In this post I am going to share with you the installation and running the first basic project. I have used Android Studio in Windows 7 and Xubuntu 12, and apart from some issues I have faced [Which I will discuss later in the post] the installation and setup is pretty easy. For Mac, I have heard from friends that it works seamlessly in their systems, and found no-problems working on it. Apart from that I haven’t had mac machine to face and test many problems.

So First, lets prepare our Machines to install the android studio. Which as of now requires JDK installed. If you have android SDK installed it will be surplus to you, but IMO android studio comes with it’s own bundle of SDK which will be installed when android studio installed itself.

To get started, download android studio from here. Like eclipse’s beloved ADT bundle, Android Studio is available in all three major Desktop OSes. And After downloading installation is pretty straight forward, in case it’s not Google has documented the instruction nicely.  And following them will make your android studio installed properly.

Android studio requires the path of proper JDK installation to work with, the launcher script of android studio is written to find out the path it self, which is JavaHomePath/bin/java, where JavaHomePath is the home directory where your java installed. If you are aware about such path exists on your system, copy it to a new environmental variable called JAVA_HOME before you start android studio for the first time.

So far this story is pretty much known to those enthusiasts who have already downloaded android studio and working with it. And you can find the issue and it’s solution in stackoverflow, google groups, many blogs and nearly every android development forums. But there was one problem I faced and couldn’t find proper solution online, Finding a solution myself lead me to the place where setting up new environmental variable became optional when the launching script can not find a proper java path installed, and still you can start working with android studio.

Ubuntu does not have Oracle’s JDK pre-installed and even they don’t have an easy way to install it directly, and generally they use OpenJDK as the replacement of Oracle’s JDK. Google has developed Android Studio such a way that OpenJDK is not advised to use [It gives some error message when Android Studio finds OpenJDK is default JDK in system and we can not start Android Studio.

There are some workarounds exist. We have to download Oracle’s JDK installer and add it into `usr` or set newly downloaded Java’s path as any system variable. But to do that we must have fully functional Admin access of the system, and not all users are lucky to have that.

Thankfully Android Studio’s running script is an sh file that we can study and edit as per our need. When I studied the script I found that Android Studio just needs a path from where it can pick some essential java tools so it can work smoothly. The purpose of having a system variable to have such path handy and available all the time. But this is not the only case. We can refer to an external path which script can access with all permission needed and Android Studio can work around this path as well.

And a Modified Script is born.

The addition on the original studio.sh script are as follows.

1. At first it tries to read something from path.config file if it exists. If not found it will look for other system variable for proper Java path.

refer lines 36 to 40 on above gist to see how it works.

2. If none of the Java path are proper [Esp it happens when Open JDK is found] It usually throws error and exits. I have modified a script around it so user can be able to insert any proper custom path for JDK and after check this path will be written in path.config file stated on step 1.

refer lines 126 to 134 to see how it works.

[Note: If you can not see the gist properly, you can always go to the original gist here]

This is it. Now after passing any possible hurdles, the android Studio is up and running. If you know how to setup android sdk and create a project in eclipse, the procedure for the same action in Android Studio doesn’t differ a bit. If you don’t know head to android developers’ official training guide to make yourselves familiar for that.

If you are familiar to android and it’s development with eclipse I suggest you to start reading Mark Ellison’s recent blogpost about the new gradle build system in Styling Android. Please note that this series is not completed, it’s taking shape. I request you to read it because he’s diving deep into Gradle which we are to cover next in this series, only the part we need to create a normal app of our need.

The Android Studio Story : 1- A whole new world

In their recent Google I/O event, Google was focusing more on development front rather than announcing new product for general public. They tried to make development easy for their other services including their most evolving platform – android. Announcing new services, new guides and a lot of improvement over their current tools, but most important and exciting announcement according to me was their own IDE for android and related development. Called android studio.

Traditionally developers (including me and you) use eclipse IDE’s powered with ADT bundles are being used for android development. They are being used for “ages”, are stable(kind of) and you can get a lot of help from a lot of forums. At some point of history people are also started using IntelliJ Idea for android development, and support for it is growing up as well, but still too many people use Eclipse.

In their announcement on Google I/O keynote, Google engineers Tor Norbye and Xavier Dourchet demonstrated android studio, based on community edition of IntelliJ. Instead of traditional ANT based build, transforming to Gradle based builds, which will be core part of Android Studio build system. Thus making us, the developers relying on eclipse to explore the whole new world.

Here from this post, we are planning to write a series which will help us, the eclipse-rs to move and adopt quickly to the new IDE and development environment. The aim of the series is to know android studio, learn and experience their awesome set of features, learn how we can do some tasks in Android Studio as good as we are doing in eclipse, and be ready to propel with android studio when the time will come.

Right now, Google still supports eclipse and IntelliJ but their main focus is on stabilizing android studio. And they are doing it very fast. Within one and half months of it’s launch Android Studio has evolved from 1.1 to 1.9 (At the time of writing-03 Jul 2013), and while you are reading this, there will be more updates that will make it stable.

So for the first and introductory post, I will share couple of tables that compares Eclipse and Android Studio at a glance. And compare some useful and quick-to-figure out shortcuts.

Here is first table that compares how projects structure is referred in both the IDEs.

1. Project Structure

Apk Location : projectPath/bin-Only unsigned-Visible in eclipse and file explorer as wellApk Location : projectPath/build/apk- Unsigned, and signed apk with gradle config- Not Visible in android studio, Visible in File explorer

In Eclipse

In Android Studio

Workspace

Project

Project

Module

Build : ANT

Build : Gradle

Apk Location : projectPath/bin

-Only unsigned

-Visible in eclipse and file explorer as well

Apk Location : projectPath/build/apk

– Unsigned, and signed apk with gradle config

– Not Visible in android studio, Visible in File explorer

Here is another table that compares some handy  or quick to figure out shortcuts in both the IDEs.

2. Shortcuts

Legends : ~C = Ctrl, ~S = Shift, ~A = Alt, ~T = Tab , Normal keys are used without ~.

For readability AS = Android Studio.

Command

Eclipse Shortcut

AS Shortcut

Notes

Open any resources file

~C+~S+R [As open resource]

~C+~S+N [As open resource]

Go to source

F3

F4

Find occurrences

~C+K [While word is selected] ~C+F then next or ~C+K

~C+F then F3

this is for forward direction, to move backward, press ~S along with shortcut.

Last edited location

~C+Q

~C+~S+Backspace

Quickfix

~C+1

~A+Enter

Android studio also enters intention action which is bit better than only quickfixes.

Format source

~C+F

~C+~A+L

Organize imports

~C+~S+O

~C+~A+O

Search in project

~C+H

~C+~S+F

For eclipse it opens window for java search, file search, task search, git search etc.

For AS it opens equivalent of project search

Search all reference in Java

~C+~S+G

~A+F7

AS gives much more structured detail in every file. Both needs at least something to be selected.

Go to next method

N/A

~A+Up or Down Arrow

Depends on direction

Go to line

~C+L

~C+G

AS gives option to go to specific position as well, 151:8 will lead to line no 151 position 8.

Go to end/Start of block

~C+~S+P

~C+[ (When @ end)

or

~C+] (When @ start)

If you are at start of the brace pressing ~C+[ will send you to parent opening brace.

When you are end of the brace pressing ~C+] will send you to parent’s closing brace

Delete whole line

~C+D

~C+Y

~C+D in AS will copy whole selected block to down. If nothing is selected, it will copy whole line.

Redo

~C+Y

~C+~S+Z

Renaming

~A+~S+R

~S+F6

Extract as Variable

~A+~S+L

~C+~A+[V,P,C,F]

V – Local variable

P – Parameter to method

C – Constant

F – Field.

Choose whatever is needed.

Extract as method

~A+~S+M

~C+~A+M

Change method signature

~C+~S+C

~S+F6

This is it for today, In next post of the series we will study some common problems while installing and normal project structure.

Android Navigation drawer with actionbarsherlock

We the developers used to call this thing slide0ut menu, fly-in menu or any other name. Last week it’s been made official by google on the ocassion of their annual developer event Google I/O and named them android navigation drawer.  This thing is widely popular when facebook introduced it in android and iOS apps a while ago. And there has been some google developed apps in android like google plus, and youtube as well. Here are the screenshots.

All Navigation Drawers. From left to right: youtube, Music and Facebook

In the last week of google  announced a new navigation pattern called Android navigation drawer. Along with guideline and sample which requires latest version of android support library v13. Here is how you will implement in your application.

To start working with this, you first need to update to latest android support library, which is v13. If you are using maven, It should be updated via pom.xml. As I am new to maven, I have decided to use traditional replace approach, i.e. delete the old, replace the new. :).

Layout

1 . Ok, once you have Successfully added latest support library, start editing your layout first. Here your root element of your layout xml must be

android.support.v4.widget.DrawerLayout

2 . Here you need to add android name space, an id and width and height parameter. After adding necessary parameters your code should look like below.

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/drawer_layout"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
</android.support.v4.widget.DrawerLayout>

3 . We are prepared to have our drawer layout, now it’s time to have a framelayout, and a list view . The list view will work as slide out items’ list, and framelayout will be kind of placeholder for your actual layout. Which eventually will be attached via fragments.

Below is the code to add them in the layout.

<FrameLayout
 android:id="@+id/content_frame"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />
 <!-- The navigation drawer -->
<ListView
 android:id="@+id/left_drawer"
 android:layout_width="240dp"
 android:layout_height="match_parent"
 android:layout_gravity="start"
 android:background="#111"
 android:choiceMode="singleChoice"
 android:divider="@android:color/transparent"
 android:dividerHeight="0dp" />

4 . Thus your final layout will look something like this.

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/drawer_layout"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
<FrameLayout
 android:id="@+id/content_frame"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />
 <!-- The navigation drawer -->
<ListView
 android:id="@+id/left_drawer"
 android:layout_width="240dp"
 android:layout_height="match_parent"
 android:layout_gravity="start"
 android:background="#111"
 android:choiceMode="singleChoice"
 android:divider="@android:color/transparent"
 android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

Here, we are prepared with layouts. Now it’s time to handle the layout and events in java class

Java

1. Define drawerlayout objects in onCreate method, it’s better to write a separate method for readability.

        drawer = (DrawerLayout) findViewById(R.id.drawer_layout);        
        adapter = new DrawerAdapter(this, R.array.drawerArray);        
        drawerList = (ListView) findViewById(R.id.left_drawer);        
        actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer,R.drawable.ic_drawer, R.string.open_drawer,R.string.close_drawer) {
            @Override
            public void onDrawerOpened(View drawerView) {
                // TODO Auto-generated method stub
                super.onDrawerOpened(drawerView);
            }
        };

2.  Note here: our drawer is actually a listview, that allows us to write custom or predefined adapters. That gives us more flexibility and creativity to define and layout our drawer. I have made a custom adapter out of BaseAdapter to draw custom list which defines different colors and adds tags to each list item.

        drawerList.setAdapter(adapter);

3.  To Listen to each item click, we usually setOnItemClick listener on list, that’s exactly we need to do here.

 drawerList.setOnItemClickListener(this);

4.  The below line is to listen to open and close events on drawer itself.

 drawer.setDrawerListener(actionBarDrawerToggle);

5.  At this stage we have defined the layout of drawer and populated it with desired data. Now we need to listen to each click of the drawer. And we have already implemented OnItemClickListener, which asks us to override onItemClick method. On this stage we need to define and handle transactions of fragments. If you are not familiar with fragments, it’s the right time to study fragments api. This is the place where our implementations are going to differ. Here is the placeholder example for it.

    @Override
    public void onItemClick(AdapterView parent, View view, int position, long id) {
        // TODO Auto-generated method stub
        openFragment(position);
    }

    private void openFragment(int position) {
        FragmentManager manager = getSupportFragmentManager();
        switch (position) {
        case 0:
            FragmentOne firstFragment = new FragmentOne();
            manager.beginTransaction()
                    .replace(R.id.content_frame, firstFragment).commit();
            break;
        case 1:
            FragmentTwo otherFragment = new FragmentTwo();
            manager.beginTransaction()
                    .replace(R.id.content_frame, otherFragment).commit();
            break;
        case 2:
            AppPrefsFragment prefsFragment = new AppPrefsFragment();
            manager.beginTransaction()
                    .replace(R.id.content_frame, prefsFragment).commit();
            break;

        default:
            break;
        }
        drawer.closeDrawer(drawerList);

    }

And viola!! We have our navigation drawer ready.

Notes

1. Works really well with actionbar sherlock. Infact the java part of the code above is the same code which works with actionbarsherlock. Except one thing. With ABS we can not set drawer open or close on icon click

2. As per android guidelines actionbar will always be present whether drawer is opened or not. So we have to be careful while putting action items while drawer opened or closed

3. This works well with single activity, many fragments approach. However we are free to open activities, but to provide consistency either we have to stick with fragments, or provide drawerlayout everywhere.

4. The layout elements from xml files seems to be compulsory for me (Any corrections are welcome)

5. Again, as the drawer is a list, we can do anything with that, As shown in screenshot multilayered draweritems can be possible. Adapter is our magic hat here.

Some cool android text and time hacks for developer

In recent development I have come to know with some really cool utilities or “programming hacks”, which may go unnoticed for you but chances are that you are going to use them a lot once you are familiar with it.

Note: I don’t know how much they are performance friendly or how good they are compared to any of the equivalent solutions exist. Expert advice are always welcome.

So lets start with them.

1. Time since last……

Ever wondered how android social networking apps show “X minutes(seconds) ago” text (somewhere) near their status updates? do they fetch them from servers? No, there is a utility for that,

DateUtils.getRelativeTimeSpanString method gives you opportunity to show how much time is spent till now since “last status was updated” or “last run was scored” or even “you crossed that location”. Here is the demo for you are looking for

// Here we will go back to each minute and see how this tool will work
private void relativeTimeSpanStringDemo(TextView text) {
long now = System.currentTimeMillis();
long time = System.currentTimeMillis();
String textToShow = "";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (int i = 0; i &lt; 10; i++) {
time -= 60 * 1000; // subtract 1 minute
final String formatText = sdf.format(new Date(time));
textToShow += "\n"
+ formatText
+ " - "
+ DateUtils.getRelativeTimeSpanString(time, now, DateUtils.SECOND_IN_MILLIS,
DateUtils.FORMAT_ABBREV_ALL);
}
text.setText(textToShow);
}

2. Expandable templates


Suppose in your application you have to write this statement gazillion of times

“You have been invited to {event} by {user} , at {place} on {time}. The event will be finished by {time}, in any queries please contact {me} on {this email id}”

How many concatenations you have to make to give sense to the above string? atleast 8, and what if this string is being generated at too many places and you have neither spirit nor opportunity to have a common logic to be applied? You may be doomed, you are going to handover your republic to an evil sith empire. You will think a common solution can not exist. And you start to have a bad feeling about this…..

But wait, there is A New Hope, just use expandTemplate method. As shown below.

private void expandTemplateDemo(TextView text) {
String template = "You have been invited to ^1 by ^2";
text.setText(TextUtils.expandTemplate(template, "Barca VS PSG match", "Prasham Trivedi"));
}

This method except at most 9 variables.

And Many More………..

Now you have a status that has been liked by harry, ron, hermione, lucius fox, han solo and even the great odin of asgrad!! And you are Bruce Wayne or Commissioner Gordon, only care about people from your universe the rest are numbers. How you would represent this in a proper way?

Just call TextUtils.commaEllipsize. And you will have a result.

Note: It will require two additional variables 1. paint and 2. width. The paint variable can be created by calling new Paint(), if you have access to any textView, you can get the same by calling textView.getPaint…

Width can be measured by calling paint.measureText(), argument passed here should be the text you want to retain…

Here is another football world example…

private void commaEllipsizeDemo(TextView text) {
 final String string = "Barca,Madrid,Gala,PSG,Dortmund,Munich,Juventus,Malaga";
 final TextPaint paint = text.getPaint();
 final float measureText = paint.measureText("Barca,Madrid,Gala,PSG,Dortmund");
 text.setText(TextUtils.commaEllipsize(string, paint, measureText, " and one more",
 " and %d more"));
 }