TSM - Today Software Magazine - Android client

3Pillar Global Team India - 3Pillar Global Team India

The arrival of Today Software Magazine back in March 2012 infused life into the IT community in Romania. It provided voice to the many talented IT and software development professionals who were looking for a common platform to showcase their expertise, share best practices, and find solutions to various problems impacting the industry.

Today Software Magazine has grown in strength from its first issue of four articles to the latest issue, #17, which is comprised of twelve contributions on topics like agile continuous improvement, Scrumban (a combination of Scrum and Kanban), and the real-time web.

At 3Pillar, we are proud to have been associated with Today Software Magazine pretty much from the start. As we wrote about it previously, members of our team in Romania managed to develop the iPhone and iPad apps for Today Software Magazine in six weeks flat.

Building on the success of the iPhone/iPad app, our development team started working on the Today Software Magazine Android application.

https://play.google.com/store/apps/details?id=com.tpg.tsm.ui&hl=ro

The beginning of process

After hearing a potential opportunity for development of an Android app from Dan Suciu (Director Engineering - Cluj), The Android CC team in India led by Anjula Pahuja(PGM) and Vineet Aggarwal (Android CC lead) started working on scope of android version and a team of 3 people (Ravindra Prajapati , Khushboo Kaur and Priyanka Singh) was created to deliver the project.

The 3Pillar team of Software Engineers followed APLM approach and created 3 sprints of 2 Weeks each. The role of the Project Manager (Vineet Aggarwal) was instrumental in adhering to the set timelines identified for each of these sprints and helped the team technically and providing status on progress to both client and management. As per APLM approach, each sprint has a specific theme and the team showcased demo to client at the end of each sprint to take inputs and further improve the delivery in subsequent deliveries.

Project progress was tracked closely using JIRA and all the respective tasks were created as user stories and assigned to the respective developer on JIRA to keep track of the development time and completion date. GIT was selected code repository tool and a development branch was created for developers at the start of Sprint 1. To avoid any conflicts, the master branch was merged with the development branch at the end of sprint and tagged with subsequent sprint version after following the code review process.

As per client discussion, the team was told to complement iPhone app design and features, but the team came up with its own suggestions following APLM accepted by client. Here are the set of features proposed:

Refresh functionality: On subsequent launch, we suggested there could be two ways to inform users about new content. One is using push notification which would let app know that a new content is available and then the user can make a call to update the content. The second is providing a manual Refresh functionality which would enable users to take the decision to check for new content. As per business requirements, refresh functionality was chosen and it enables app to check for new versions of the magazine whenever available.

Sharing on Social Networks: We got an additional requirement to share the issue url on Facebook and twitter. We suggested to the client to use 3PillarLabs SocialAuth Android library which helped them to share content on social networks, even if the user has not installed Facebook and twitter on their devices.

Supporting of app to Android GingerBread 2.3.3 as by the time of development it contains 25% market share as per latest statistics of Android Market. Further we suggest to port the app to 7"" tablets as a large percentage of android users use them.

Application architecture

The application starts with a splash screen and provides options to the user to make their language selection between "English" and "Romania". On clicking the language button, the app starts retrieving the image of the latest issue and articles from the TSM web server. It then downloads the data saved in internal memory and SQLite database.

After downloading the information pertaining to the latest issue, the app launches the home screen and shows the TSM home screen with all the downloaded issues and articles. On clicking the action bar menu icon, a user can open the left navigation drawer that contains a list of issues downloaded from the server. In the right panel screen it will show the list of articles from the selected issue.

Clicking on any article will open the TSM article viewing screen, where a user can read the full article and details of author. On clicking the share icon, the app launches a pop-up menu with options to share on platforms like Facebook, Twitter, and Mail. Language selection can be changed by clicking settings from the action bar. Once the new language change is selected, the app will erase all the stored data and restart to download content in the new selected language format.

Tools and library used

Eclipse: Eclipse IDE was chosen as application development tool due to its proximity with developers.

Charles Proxy : This tool help us during API testing and check the iPhone app flow.

SocialAuth Android Library: The API enables user authentication and sharing updates through different various social networks and hides all the intricacies of generating signatures & token. Used for sharing of articles on social networks and mail.

Android-app-v7-appcompat: Action bar support comes in Android 4.0. This library supports the Android action bar implementation in Android lower versions. Implementing the action bar removes the dependency on the Android option button.

I3P Android: Developed by 3Pillar Labs, this library helps us to create custom left navigation bar for our use case.

Challenges

The following sections highlight the challenges received by team during development and testing. It tell how we identify the problem and what it take solve the problem.

Bitmap optimization

Problem identification

The TSM home screen showed a list of articles from the selected issue along with author bitmaps. The team found that the images received from server needed to be downsized in order to avoid OutOfMemory error as it may result to crashing of application in some user scenarios

Solution

To effectively handle the OutOfMemory issue, we used bitmap sampling, a process to develop a downsize image from an existing image. The major challenge was to maintain the aspect ratio of the original image, thereby retaining the quality of image during its re-sizing. Presented below is a sample code to calculate the image sample size:

public  int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
	final int height = options.outHeight;
	final int width = options.outWidth;
	if(height<0 || width < 0)
		return -1;
	int inSampleSize = 1;
	final int heightRatio = Math.round((float) height / (float) reqHeight);
	final int widthRatio = Math.round((float) width / (float) reqWidth);
	inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
	  return inSampleSize;
}

Create new Image

public Bitmap sampleBitmap(BitmapFactory.Options options,int reqWidth, int reqHeight, TSMBaseActivity activity, String id, InputStream imageResponse, String imagePath) throws IOException {
    int sampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    if (sampleSize >= 0) {
options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;

if(haveNetworkConnection(activity.getBaseContext())){
	try{
		imageResponse=new HttpRequest(activity.getBaseContext()).getHttpInputStream(imagePath); //FileNotFoundException, MalformedUrlException
	}catch(IOException e){
		e.printStackTrace();
		if(e instanceof SocketException || e instanceof SocketTimeoutException){
		}
		return null;
	}
	if(imageResponse!=null){
		Bitmap bmp = BitmapFactory.decodeStream(imageResponse, null, options);
		if(bmp==null)
			return null;
		saveToInternalSorage(bmp, activity,id);
		return bmp;
	}
}
}
    return null;
}

YouTube Video Play

Problem identification

A lot of articles received from TSM server contained embedded Youtube videos. Playing YouTube videos inside a web view is a very challenging task, because you don"t have controls on web view. Also, the implementation varies on devices for Gingerbread and ICS devices. For instance, In Gingerbread devices, the youtube videos used to run by default on full screen whereas in ICS devices and above devices users have to manually enable the full screen.

Solution

We considered separate approaches for Gingerbread and ICS devices. For GingerBread, we used Android default Videoview control whereas for ICS and above devices we made use of Java reflection API to seamlessly play the videos. Using the reflection API, we got the reference of HTML5VideoFullScreen$VideoSurfaceView from webkit and play the full screen video. For both the versions, sample code is pasted below:

YouTube video in Android 2.3.3

VideoView customVideoView = (VideoView) customViewContainer.getFocusedChild();
Field mUriField = VideoView.class.getDeclaredField("mUri");
mUriField.setAccessible(true);
Uri uri = (Uri) mUriField.get(customVideoView);

YouTube video in Android 4.0

Class _VideoSurfaceView_Class_ = Class.forName("android.webkit.HTML5VideoFullScreen$VideoSurfaceView");
java.lang.reflect.Field _HTML5VideoFullScreen_Field_ = _VideoSurfaceView_Class_.getDeclaredField("this$0");
_HTML5VideoFullScreen_Field_.setAccessible(true);
Object _HTML5VideoFullScreen_Instance_ = _HTML5VideoFullScreen_Field_.get(((FrameLayout) view).getFocusedChild ());

Improving App performance

Problem identification

Fetching TSM data in an asynchronous manner in the application and then showing the data on the UI was taking approx. 20-25 minutes. This is definitely a large time. To reduce the complexity, a number of different processes were created. Each of them was doing its own task of downloading data from the server. The difficult part in this is the synchronization among them and avoiding any conflict. Author Images cannot be downloaded until the Author information is downloaded as the path of the image is contained in the Author Information. Thus the challenge was to optimize the data downloading time and thereby improving application"s performance.

Solution

We have implemented ThreadPoolExecutor. All the tasks are attached with the executor. Initially the thread pool was created with size as 2 allowing two threads to execute in parallel. As soon as these threads finish the threads from the pool are queued to download the content as the user browses the application.

ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 2,60, TimeUnit.SECONDS, new ArrayBlockingQueue(2), threadFactory);
executorPool.execute(new LoadIssueImages(handler, language,getBaseContext()));
executorPool.execute(new LoadIssueArticles(handler, language,getBaseContext()));
executorPool.execute(new LoadAuthorInformation(handler,language, getBaseContext()));
executorPool.execute(new LoadAuthorImages(handler, language,getBaseContext(), this));

Testing

The app was tested for following devices: Nexus 4 (Android 4.3) , Nexus 7(Android 4.1, 7"" Tablet) , HTC Desire (Android 2.3.3 , 480x800) and Samsung Tab(7",10") , Galaxy Y(240x320).

We have selected the above devices to cover the major range of android devices on the market, based on our experience. The testing team used the following set of testing methodologies to ensure that the app experience should not break while being used:

First Time App Launch Testing: When mobile app is installed successfully an app icon will be created. On tapping the App icon, a splash screen is displayed.

API Testing: We verified the iPhone app flow using Charles Proxy tool. The idea is to provide the same user experience as we have in iOS.

Network Scenario Testing: We verify the behavior of application when there is a Network problem and the user is performing operations for data call. Users get proper error messages like "Network error. Please try again later."

Stress Testing: An important way of ensuring the stability of the app being developed. For this we tested the app by quickly tapping on multiple button/links/link images etc. By making such multiple requests at the same time, we tried to improve the app stability.

Testing with Different Network Types: The app was tested with various network types 2G, 3G and Wi-Fi.

Testing with Devices of Different Resolution: We tested the app on a variety of screen resolutions ranging from 240x320 to 1280x800. Due to the availability of selected devices, the team tried to make sure that the app would work on different screen resolutions and mimic their behavior. For instance, 10"" tablet takes portrait orientation as landscape. Also the UI was different for tablets and devices.