Tutorial #90: Implement Media Style Notifications in Android

UPDATE: According to the latest release, the createSession() method has now been removed from the MediaSessionManager class. The below tutorial will hence not work as expected. Sorry for the inconvenience. I will try and post a working tutorial soon! 🙂

SOLUTION: I have fixed the above problem and the working code can be found over here. Sorry for the delay.

Hello everyone!

Even before Google officially launched the Android 5.0 (Lollipop) SDK, a preview to the same was made available to developers to experience the new features. Apart from material design, another interesting feature was Notifications. The Android L (Preview SDK) added a new lock screen notification feature called Notification.MediaStyle. Up until this point lock screen media controls had to be implemented through the use of a RemoteView.

Starting from Android 5.0 (Lollipop), lock screen notifications are now displayed using Notification.MediaStyle template with the addAction() method, which converts actions into clickable icons. Through this tutorial, we will learn how to implement media style notifications in Android.

Pre-requisites: Eclipse IDE, Android SDK (L Preview)

Step 1: Create Android project

Create a new Android application project called AndroidLollipopExamples with both the build target and minimum SDK set to Android L (API level L). Let the package name be com.app.android.lollipop.

Step 2: Create Service class

In order to implement the media style lock screen notification, we need to create a Service class that will contain the various media controls & media session callbacks. Create a new class called MediaPlayerService and write the following code!

MediaPlayerService.java

package com.app.android.lollipop;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.Rating;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.os.IBinder;
import android.util.Log;

public class MediaPlayerService extends Service {

    private MediaPlayer m_objMediaPlayer;
    private MediaSessionManager m_objMediaSessionManager;
    private MediaSession m_objMediaSession;
    private MediaController m_objMediaController;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void handleIntent( Intent intent ) {
        if( intent == null || intent.getAction() == null )
            return;

        String action = intent.getAction();

        if( action.equalsIgnoreCase( Constants.ACTION_PLAY ) ) {
            m_objMediaController.getTransportControls().play();
        } else if( action.equalsIgnoreCase( Constants.ACTION_PAUSE ) ) {
            m_objMediaController.getTransportControls().pause();
        } else if( action.equalsIgnoreCase( Constants.ACTION_FAST_FORWARD ) ) {
            m_objMediaController.getTransportControls().fastForward();
        } else if( action.equalsIgnoreCase( Constants.ACTION_REWIND ) ) {
            m_objMediaController.getTransportControls().rewind();
        } else if( action.equalsIgnoreCase( Constants.ACTION_PREVIOUS ) ) {
            m_objMediaController.getTransportControls().skipToPrevious();
        } else if( action.equalsIgnoreCase(Constants.ACTION_NEXT ) ) {
            m_objMediaController.getTransportControls().skipToNext();
        } else if( action.equalsIgnoreCase( Constants.ACTION_STOP ) ) {
            m_objMediaController.getTransportControls().stop();
        }
    }

    private Notification.Action createAction( int icon, String title, String intentAction ) {
        Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class);
        intent.setAction( intentAction );
        PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 1, intent, 0);
        return new Notification.Action.Builder( icon, title, pendingIntent ).build();

    }

    private void buildNotification( Notification.Action action ) {
            Notification.MediaStyle style = new Notification.MediaStyle();
            style.setMediaSession( m_objMediaSession.getSessionToken() );

            Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
            intent.setAction( Constants.ACTION_STOP );
            PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 1, intent, 0);
            Notification.Builder builder = new Notification.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle( "Sample Title" )
                    .setContentText( "Sample Artist" )
                    .setDeleteIntent( pendingIntent )
                    .setStyle(style);
            

            builder.addAction( createAction( android.R.drawable.ic_media_previous, "Previous", Constants.ACTION_PREVIOUS ) );
            builder.addAction( createAction( android.R.drawable.ic_media_rew, "Rewind", Constants.ACTION_REWIND ) );
            builder.addAction( action );
            builder.addAction( createAction( android.R.drawable.ic_media_ff, "Fast Foward", Constants.ACTION_FAST_FORWARD ) );
            builder.addAction( createAction( android.R.drawable.ic_media_next, "Next", Constants.ACTION_NEXT ) );

            NotificationManager notificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
            notificationManager.notify( 1, builder.build() );
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if( m_objMediaSessionManager == null ) {
            initMediaSessions();
        }

        handleIntent( intent );
        return super.onStartCommand(intent, flags, startId);
    }

    private void initMediaSessions() {
        m_objMediaPlayer = new MediaPlayer();
        m_objMediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
        m_objMediaSession = m_objMediaSessionManager.createSession("sample session");
        m_objMediaController = MediaController.fromToken( m_objMediaSession.getSessionToken() );

        m_objMediaSession.addTransportControlsCallback( new MediaSession.TransportControlsCallback() {
            @Override
            public void onPlay() {
                super.onPlay();
                Log.e( Constants.LOG_TAG, "onPlay");
                buildNotification( createAction( android.R.drawable.ic_media_pause, "Pause", Constants.ACTION_PAUSE ) );
            }

            @Override
            public void onPause() {
                super.onPause();
                Log.e(Constants.LOG_TAG, "onPause");
                buildNotification(createAction(android.R.drawable.ic_media_play, "Play", Constants.ACTION_PLAY));
            }

            @Override
            public void onSkipToNext() {
                super.onSkipToNext();
                Log.e(Constants.LOG_TAG, "onSkipToNext");
                buildNotification( createAction( android.R.drawable.ic_media_pause, "Pause", Constants.ACTION_PAUSE ) );
            }

            @Override
            public void onSkipToPrevious() {
                super.onSkipToPrevious();
                Log.e(Constants.LOG_TAG, "onSkipToPrevious");
                buildNotification( createAction( android.R.drawable.ic_media_pause, "Pause", Constants.ACTION_PAUSE ) );
            }

            @Override
            public void onFastForward() {
                super.onFastForward();
                Log.e(Constants.LOG_TAG, "onFastForward");
            }

            @Override
            public void onRewind() {
                super.onRewind();
                Log.e(Constants.LOG_TAG, "onRewind");
            }

            @Override
            public void onStop() {
                super.onStop();
                Log.e(Constants.LOG_TAG, "onStop");
                NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.cancel( 1 );
                Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
                stopService( intent );
            }

            @Override
            public void onSeekTo(long pos) {
                super.onSeekTo(pos);
            }

            @Override
            public void onSetRating(Rating rating) {
                super.onSetRating(rating);
            }
        });
    }

    @Override
    public boolean onUnbind(Intent intent) {
        m_objMediaSession.release();
        return super.onUnbind(intent);
    }
}

Constants.java

package com.app.android.lollipop;

public class Constants {

	public static final String ACTION_PLAY = "action_play";
	public static final String ACTION_PAUSE = "action_pause";
	public static final String ACTION_REWIND = "action_rewind";
	public static final String ACTION_FAST_FORWARD = "action_fast_foward";
	public static final String ACTION_NEXT = "action_next";
	public static final String ACTION_PREVIOUS = "action_previous";
	public static final String ACTION_STOP = "action_stop";
	public static final String LOG_TAG = "MediaService";
	
}

Step 2: Create Activity class

Create a new Activity class called MediaPlayerActivity that will start the above service.

MediaPlayerActivity.java

package com.app.android.lollipop;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class MediaPlayerActivity extends Activity{

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		Intent intent = new Intent( getApplicationContext(), MediaPlayerService.class );
		intent.setAction( Constants.ACTION_PLAY );
		startService( intent );
	}
}

Step 3: Add permission in Manifest file

It is important for developers to add the new MEDIA_CONTENT_CONTROL permission in the AndroidManifest.xml file in order to implement the media style notification.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.app.android.lollipop"
    android:versionCode="1"
    android:versionName="1.0">

    <uses-sdk
        android:minSdkVersion="L"
        android:targetSdkVersion="21" />

    <permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name">
        <activity
            android:name=".MediaPlayerActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.app.android.lollipop.SecondActivity"
            android:label="@string/app_name" />
        
        <service android:name=".MediaPlayerService"/>
   
     </application>
</manifest>

Save all changes. Make sure no errors are present. Run the application on an Android L emulator and you should see the following output!

media style notification

media style notification

Reference: Android Notifications

AngularJS: Form validation

Hello everyone!

In my previous post we learnt how to get started with AngularJS. In general, forms and controls provide validation services so that the end user can be notified of invalid input. As mentioned on the developer’s page, the ng-submit directive prevents the default action (which for form means sending the request to the server and reloading the current page). In Angular, one can submit a form either using a button element with an ng-click attribute or by using the ng-submit directive.

Through this post we will learn how to implement form validation in AngularJS.

Pre-requisites: Windows 7, Notepad or any text editor

Launch Notepad or any text editor and create a new HTML page called form_validation.html as follows.

form_validation.html

<!DOCTYPE html>
<html ng-app="demo">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
	
	<style type="text/css">
	    
        .ng-invalid.ng-dirty{
		  border-color: #FA787E;
		}
		
		.ng-valid.ng-dirty{
		  border-color: #78FA89;
		}
	</style>
	
  </head>
  <body>
	
	<div ng-controller="ListController">

	    <h2>List of submissions </h2>  
		<ul>
		   <li ng-repeat="student in students">
		     Name: {{ student.name | uppercase}}
		     Email : {{ student.email | lowercase }}
		     City: {{ student.city | uppercase}}
		  </li>	   
		</ul>
	
		<h2>Please fill the below form</h2>
		
		<form ng-controller="FormController" name="myForm" ng-submit="myForm.$valid && addStudent(student)" novalidate>
		
    	  Name: <input type="text" ng-model="student.name" placeholder="Enter your name" required/> <br>
		  Email: <input type="email" ng-model="student.email" placeholder= "Enter your email addresss" required/> <br>
		  City: <input type="text" ng-model="student.city" placeholder="Enter your city"/> <br>
		  
		 <input type="submit" value="Submit"/>
	
		</form>
		 	
	</div>

	<script type="text/javascript">
		
		var app = angular.module("demo",[]);
		app.controller("ListController", function($scope){
		    $scope.students = [
				{ name: 'Hari', city: 'Mumbai', email:'hari@gmail.com'},
				{ name: 'Alexander', city: 'Paris', email:'alex@gmail.com'}
			];
		});
		
		app.controller("FormController", function($scope){
			$scope.addStudent = function(student){
				$scope.students.push(student);
			};
		});
		
	</script>
	
  </body>
</html>

Open the above page in a web browser. If no errors occur then you should see the following output before and after the form submission!

output_1

output_2

That’s it for this AngularJS tip. Stay tuned for more! 🙂

Getting started with AngularJS!

The web is constantly evolving. Earlier, when a browser sent a request to the web server, the server would respond with the corresponding webpage & assets required to load the page. However, when a user clicked a link on the page, the browser would download the same files again. AngularJS is an open source web application framework designed to overcome such limitations. It is maintained by Google and the community at large.

AngularJS is by far one of the most popular technologies for developing MVC based web applications. It supports rapid front end development including features such as two way data binding, dependency injection, custom directives etc with the goal of improving testability and performance. Through this post, we will learn how to get started with AngularJS.

Pre-requisites: Windows 7, Notepad or any text editor, JavaScript

Modules

Modules are used to define applications. A module acts as a container for the different parts of an app, including directives, controllers, services etc. All application controllers should belong to a module. For example,

<div ng-app="demo">
 {{ Hello, Angular!}}
</div>

A reference has been made to the demo module using the ng-app directive.

Directives

AngularJS directives are basically extended HTML attributes with the prefix ng-. As mentioned on the developer’s page, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS’s HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.

Controllers

In Angular, a Controller is a JavaScript constructor function that is used to augment the Angular Scope. A Controller is attached to the DOM via the ng-controller directive.

Now, it’s time to implement the above concepts using an example. Let’s create an HTML page called test.html and write the following code.

test.html

<!DOCTYPE html>
<html ng-app="demo">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
  </head>
  <body>
	<div>
      <input type="text" ng-model="userName" placeholder="Enter a name here">
        Hello, {{ userName}}!
    </div>
	
	<h2>List of students</h2>
	<div ng-controller="ListController">
		<ul>
		   <li ng-repeat="student in students">{{ student.studentName | uppercase}}</li>	   
		</ul>
	</div>

	<script type="text/javascript">
		
		var app = angular.module("demo",[]);
		app.controller('ListController', function($scope) {
			$scope.students = [
				{ studentName: 'Hari', city: 'Mumbai'},
				{ studentName: 'Alexander', city: 'Paris'},
				{ studentName: 'Zen', city: 'Tokyo'},
				{ studentName: 'Benjamin', city: 'New York'}
			];
		});   
	</script>
	
  </body>
</html>

The above example demonstrates the use of the ng-app and the ng-controller directive. It also explains data binding using AngularJS. If you open the page in a web browser you should see the following output.

output

In the upcoming tutorials we will learn how to use some more features of Angular JS. Till then happy coding! 🙂

Reference: Angular JS Developer Guide

Implement RecyclerView in Android

Hello friends!

In one of my previous posts, I had talked about a new feature called Activity Transitions introduced in Android 5.0 Lollipop. In addition, Google has also introduced two new views namely RecyclerView and CardView. The RecyclerView widget is used primarily in applications that consists of data collections whose elements change at runtime. The change can occur either due to user action or network events.

As mentioned on the developer’s page, the RecyclerView class simplifies the display and handling of large data sets by providing,

  • Layout managers for positioning items.

  • Default animations for common item operations, such as removal or addition of items.

In order to recycle or reuse a view, a layout manager may ask the adapter to replace the contents of the view with a different element from the dataset. Through this post we will learn how to implement a RecyclerView in Android.

Pre-requisites: Eclipse IDE, Android SDK 5.0

We will be using our existing AndroidLollipopExamples project as mentioned in the previous post in order to implement the RecyclerView.

Step 1: Getting the support library

In order to use the RecyclerView one needs to download and install the latest version of the Android support library from the SDK Manager as seen below.

support_library

Once the support library is installed, navigate to the {ANDROID-SDK}\sdk\extras\android\support\v7\recyclerview directory and copy paste the .jar file present in the libs folder in your Android project. One can also import the same as a library project and add it as a reference to your existing Android project.

Step 2: Create layout for RecyclerView

Create a new XML file called activity_recycler_view.xml and write the following code.

activity_recycler_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <android.support.v7.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

Step 3: Create Adapter class

Next, we need to create an Adapter class that will bind the data to the View. Let’s call it MyAdapter. It will contain the following code.

MyAdapter.java

package com.app.android.lollipop;

import android.annotation.SuppressLint;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

@SuppressLint("InflateParams")
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

	private FruitModel[] fruitsData;

	public MyAdapter(FruitModel[] fruitsData) {
		this.fruitsData = fruitsData;

	}

	@Override
	public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {

		//create view and viewholder
		View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_fruit, null);
		ViewHolder viewHolder = new ViewHolder(itemLayoutView);
		return viewHolder;
	}

	// Replace the contents of a view 
	@Override
	public void onBindViewHolder(ViewHolder viewHolder, int position) {    
		viewHolder.txtViewTitle.setText(fruitsData[position].getFruitName());
	}

	// class to hold a reference to each item of RecyclerView 
	public static class ViewHolder extends RecyclerView.ViewHolder {

		public TextView txtViewTitle;

		public ViewHolder(View itemLayoutView) {
			super(itemLayoutView);	
			txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.fruit_name);
		}	
	}

	// Returns the size of the fruitsData
	@Override
	public int getItemCount() {
		return fruitsData.length;
	}
}

item_fruit.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:padding="15dp">

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

The layout that will be used for each item in the RecyclerView contains only one TextView at present. However, one can also add other views (eg. ImageView) if required.

Step 4: Create Activity class

The actual implementation of the RecyclerView happens in the Activity class. Here, we will get the reference to the view and populate the data required.

TestRecyclerViewActivity.java

package com.app.android.lollipop;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
 
public class TestRecyclerViewActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view);
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
         
        FruitModel fruitsData[] = { new FruitModel("Apple"),
                new FruitModel("Banana"),
                new FruitModel("Orange"),
                new FruitModel("Pineapple"),
                new FruitModel("Mango"),
                new FruitModel("Watermelon"),
                new FruitModel("Strawberry"),
                new FruitModel("Grapes"),
                new FruitModel("Jackfruit"),
                new FruitModel("Carrot"),
                new FruitModel("Fig")};
        
        //set layoutManger
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        MyAdapter mAdapter = new MyAdapter(fruitsData);
        //set adapter
        recyclerView.setAdapter(mAdapter);
        //set item animator to DefaultAnimator
        recyclerView.setItemAnimator(new DefaultItemAnimator());
 
    }
}

No changes are to be made to the AndroidManifest.xml file. Finally, make sure no errors are present. Run the application on an Android emulator and you should see the following output! 🙂

output_recycler_view

Next, we will look at implementing the CardView in Android.

Reference: Android RecyclerView

Tutorial #89: Execute batch file using Oracle Job Scheduler

Hey everyone!

The Oracle database includes a built-in scheduler that allows scheduling functions and procedures that can be called from any PL/SQL program. The DBMS_SCHEDULER package introduced in Oracle 10g helps to create, run and monitor jobs. In addition, one can also define a job to execute a batch (.bat) file.

In order to run an external job, you need to enable and start the OracleJobScheduler service on the database server. Through this tutorial, we will learn how to execute a batch file using Oracle Job Scheduler.

Pre-requisites: Oracle 11gR2 Enterprise Edition, Windows 7 (64 bit)

Step 1: Create a batch script

Let’s begin by creating a batch script called example1.bat. On Windows, launch any text editor like Notepad and include the following contents.

example1.bat

echo test > F:\programs\calling_job_from_oracle\output\sample.txt

The above batch file will output the word “test” to a text file in the output directory. The batch file will automatically create the text file upon execution.

Step 2: Create Oracle job

Open SQLPlus and log in as a user with highest privileges. Now, let’s create our job definition by executing the below commands in the console.

BEGIN
    SYS.DBMS_SCHEDULER.CREATE_JOB( job_name => 'example_job',
        job_type => 'EXECUTABLE',
        job_action => 'C:\WINDOWS\system32\cmd.exe',
        job_class => 'DEFAULT_JOB_CLASS',
        comments => 'Job to call batch script on Windows',
        auto_drop => FALSE,
        number_of_arguments => 3,
        enabled => FALSE);
 
    SYS.DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE( job_name => 'example_job', argument_position => 1, argument_value => '/q'); 
    SYS.DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE( job_name => 'example_job', argument_position => 2, argument_value => '/c'); 
    SYS.DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE( job_name => 'example_job', argument_position => 3, argument_value => '"F:\programs\calling_job_from_oracle\example1.bat"'); 
    SYS.DBMS_SCHEDULER.ENABLE( 'example_job' ); 
END;
/

As seen above, it is important to note that one can’t directly execute a batch script. Instead, we need to open an instance of the command prompt and pass an argument in order to execute the batch script. For instance, /q is the cmd.exe switch to turn off echo where as /c is the switch to terminate the same after completing the specified command. Finally, you can test the job by executing the below PL/SQL statement.

BEGIN
    DBMS_SCHEDULER.RUN_JOB( 'example_job');
END;
/

If the job is executed successfully, you should see a sample.txt file present in the output folder. That’s it for this tutorial. Hope it helps! 🙂

Reference:

1. Oracle Job Scheduler

2. Running a Windows batch file from DBMS_SCHEDULER

Activity Transitions using Android 5.0

Hello everyone!

Android 5.0 Lollipop is now officially launched by Google. The new version of Android brings in a lot more features allowing developers to create much better mobile applications. One of the key highlights of this new version includes Material Design. It is basically a comprehensive guide for visual, motion, and interaction design across platforms and devices.

Through material design, developers can also define custom animations. Android 5.0 introduces some default animations for buttons and activity transitions. Through this post, we will learn how to perform an Activity Transition in Android.

Pre-requisites: Eclipse IDE, Android SDK with Android 5.0 Lollipop

Step 1: Create Android project

Launch Eclipse IDE and create a new Android Application Project called AndroidLollipopExamples with package name com.app.android.lollipop. Choose the target SDK as Android 5.0 (API level 21). In case you don’t see the target API level 21 listed, you can download and install the same from the SDK Manager.

android_target_sdk

Step 2: Create Activity class

In order to perform a transition, we need to create two Activities. Let us name our activities as FirstActivity and SecondActivity respectively. The transition will take place while moving from the first to the second activity via an Intent. Our FirstActivity class would be as follows,

FirstActivity.java

package com.app.android.lollipop;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Bundle;
import android.transition.Explode;
import android.transition.Transition;
import android.view.Window;

@SuppressWarnings("unchecked")
public class FirstActivity extends Activity {

	@SuppressLint("NewApi")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);	
        //enable window content transition
		getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        //set the transition
		Transition ts = new Explode();  
		ts.setStartDelay(2000);
        //set the duration
		ts.setDuration(5000);
		getWindow().setEnterTransition(ts);
        //set an exit transition so it is activated when the current activity exits
		getWindow().setExitTransition(ts);
		setContentView(R.layout.activity_first);
		launchSecondActivity();
	}

	//this will call the second activity resulting in an exit transition
	@SuppressLint("NewApi")
	public void launchSecondActivity() {
		Intent intent = new Intent(this, SecondActivity.class);
		startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
	}	
}

activity_first.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/first_activity" />

</RelativeLayout>

We then need to define a transition in our next Activity as well. Here’s how the SecondActivity class will finally look.

package com.app.android.lollipop;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.transition.Slide;
import android.transition.Transition;
import android.view.Window;

public class SecondActivity extends Activity {
	
	@SuppressLint("NewApi")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
        //enable window content transition
		getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        //set the transition
		Transition ts = new Slide();  
		ts.setDuration(3000);
		getWindow().setEnterTransition(ts);
		getWindow().setExitTransition(ts);
		setContentView(R.layout.activity_second);
	}
}

activity_second.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/second_activity" />

</RelativeLayout>

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">AndroidLollipopExamples</string>
    <string name="first_activity">First Activity</string>
    <string name="second_activity">Second Activity</string>    
</resources>

Note:

Make sure you have registered the SecondActivity within the application tag in the AndroidManifest.xml file as follows!

AndroidManifest.xml

....
 <activity
     android:name="com.app.android.lollipop.SecondActivity"
     android:label="@string/app_name" />
....

Finally, make sure no errors are present. Save all changes and run the application on an emulator running Android 5.0 and you should see the activity transition taking place! 🙂

Reference: Custom Animations in Android

Create custom EditText in Android

Hello everyone!

In the past, we have seen how customizing existing Android layout widgets can help improve the overall look-and-feel of the application. There exists many applications where in input text boxes are customized to suit user requirements. Android allows developers to modify an EditText widget and use the same while designing login forms, custom controls. Developers can use a drawable as the background. This can be either a reference to a full drawable resource (such as a PNG image, 9-patch, XML state list description, etc), or a solid color such as black.

Through this post, we will learn how to customize an EditText in Android.

Pre-requisites: Eclipse IDE, Android SDK

Step 1: Create a new Activity class called CustomEditTextActivity in any of your existing Android projects and write the following code.

CustomEditTextActivity.java

package com.example;

import android.app.Activity;
import android.os.Bundle;

public class CustomEditTextActivity extends Activity {
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_custom_edittext);
	}
}

Step 2: Create custom EditText

Let’s create a new layout called activity_custom_edittext.xml in the res/layout folder of our existing Android project and add the following code.

activity_custom_edittext.xml

<?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">
    
       <EditText
           android:id="@+id/et1"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:background="@drawable/rounded_edittext"
           android:drawableLeft="@drawable/sample_image"
           android:drawablePadding="20dp"
           android:gravity="center_vertical"
           android:hint="@string/customized_text"
           android:imeOptions="actionNext"
           android:inputType="text"
           android:singleLine="true"
           android:textColor="#D00000"
           android:textColorHint="#D00000"
           android:textSize="15sp" />

</LinearLayout>

In order to customize the EditText widget, we need to define another XML that can be applied as a background attribute. Create a new XML file called rounded_edittext.xml and place it inside the res/drawable folder. The XML file will contain the below code.

res/drawable/rounded_edittext.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/rounded_edittext.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="10dp"
    android:shape="rectangle">

    <solid android:color="#F8F8F8"/>

    <corners
        android:bottomLeftRadius="4dp"
        android:bottomRightRadius="4dp"
        android:topLeftRadius="4dp"
        android:topRightRadius="4dp"/>

</shape>

Finally, make sure no errors are present. Run the application on an Android device and you should see the following output!

output

Reference: Android EditText

Load custom HTML using WebView in Android

Hey friends!

In Android, a WebView is a view used to display web pages. Developers can also create their own HTML content and use the existing methods provided by the WebView widget to load custom HTML pages. As mentioned on the developer’s page, the loadDataWithBaseURL method is used to load the given data into a WebView, using baseUrl as the base URL for the content. The base URL is used both to resolve relative URLs and when applying JavaScript’s same origin policy.

Through this post, we will learn how to load our custom HTML content using WebView in Android.

Pre-requisites: Eclipse IDE, Android SDK

Step 1: Create a new Activity class called WebViewActivity in any of your existing Android projects and write the following code.

WebViewActivity.java

package com.example;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class WebViewActivity extends Activity{

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_web_view);
		
		WebView webView = (WebView)findViewById(R.id.webview);
		StringBuilder html = new StringBuilder();

		html.append("<html>");
		html.append("<head>");

		html.append("<link rel=stylesheet href='css/style.css'>");
		html.append("</head>");
		html.append("<body>");
		html.append("<h1>Android WebView Example</h1>");
		html.append("<p>Sample text</p>");
		html.append("<p><img style='width: 100%;' src='earth.png' /></p>");
		html.append("</body></html>");

		webView.loadDataWithBaseURL("file:///android_asset/", html.toString(), "text/html", "UTF-8", ""); 
	}
}

activity_web_view.xml

<?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">

    <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

</LinearLayout>

Note: In order to access the Internet and load web pages in a WebView, you must add the INTERNET permissions to your Android Manifest file.

 <uses-permission android:name="android.permission.ACCESS_INTERNET" />

Step 2: Create a new folder called css under the assets directory of your project and copy a sample style.css file inside the folder as shown below.

assets_folder_location

Finally, make sure no errors are present. Run the application on an Android device and you should see the following output!

output

So then, that’s it for this Android tip. Keep visiting for more! 🙂

Reference: Android WebView

Android Tools: ProGuard

Hey friends!

The Android SDK comes shipped with a bunch of tools that allow developers to create even better mobile applications. It is seldom that we use these tools, mainly due to the lack of understanding or awareness. ProGuard, for instance, is one such tool that is integrated into the Android build system, so you do not have to invoke it manually.

Today, it is quite easy to reverse engineer Android applications. If one wants to prevent this from happening, one should use ProGuard for its main function i.e code obfuscation. As mentioned on the developer’s page, the ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names. Through this post, we will learn how to use ProGuard in Android.

Pre-requisites: Eclipse IDE, Android SDK

Step 1: Launch Eclipse IDE and open any of your existing Android projects.

Step 2: Enable ProGuard

Open up the file project.properties in the Eclipse text editor and uncomment the following line by removing the # symbol in the first column,

#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

Thus, ProGuard is now enabled. However, if there are any classes that you do not want to obfuscate, then the class must be added to the proguard-project.txt file as follows,

-keepclassmembers class com.app.test.TestArrowActivity {
public *;
}

Now, go ahead and create a signed APK of your Android project and use dex2jar to reverse engineer the executable APK. Here is the screenshot of a decompiled obfuscated Android APK followed by the image of a class that we chose not to obfuscate.

output_1

output_2

That’s it for this Android tip. Hope it helps! 🙂

Reference: Android ProGuard

Tutorial #88: Using JUnit framework in Android

Hello everyone!

In one of my previous tutorials, we had seen how to use the robotium framework for writing black-box tests for Android applications. Apart from Robotium, there are many tools that can be used for testing Android applications. JUnit is a unit testing framework for Java useful in test-driven development. It can also be used to test Android applications.

As mentioned on the developer’s page, Android test suites are based on JUnit. Developers can use plain JUnit to test a class that doesn’t call the Android API, or Android’s JUnit extensions to test Android components. Through this tutorial, we will learn how to use JUnit to test Android applications.

Pre-requisites: Eclipse IDE, Android SDK

Step 1: Create a new Android application project called AndroidJUnitExample with package name com.app.junit. Choose the target SDK as Android 4.4.

Step 2: Create Activity class

Let’s create an Activity class called MainActivity to display a sample text along with a button.

MainActivity.java

package com.app.jnuit;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

	private Button m_btnSubmit;
	private TextView m_tvSample;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		m_btnSubmit = (Button)findViewById(R.id.btnSubmit);
		m_tvSample = (TextView)findViewById(R.id.txtView1);
		
		m_btnSubmit.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				m_tvSample.setText("button clicked");
				finish();
			}
		});
	}
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <TextView
        android:id="@+id/txtView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/sample" />

    <Button
        android:id="@+id/btnSubmit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/txtView1"
        android:layout_centerInParent="true"
        android:text="@string/submit" />

</RelativeLayout>

Step 3: Create Android test project

Right click your existing Android project, select Android Tools -> New Test Project. Let the test project name be AndroidJUnitTest with package name com.app.junit.test.

Using the JUnit framework, we would be creating a test case to detect the change in text once a button is clicked. The test case is successful if the text of the TextView has changed to “button clicked”. In order to implement let’s create our test case class as follows.

MyTestCase.java

package com.app.jnuit.test;

import android.content.Intent;
import android.test.suitebuilder.annotation.MediumTest;
import android.widget.Button;
import android.widget.TextView;

import com.app.jnuit.MainActivity;

public class MyTestCase extends android.test.ActivityUnitTestCase<MainActivity> {


	private Intent mStartIntent;

	public MyTestCase() {
		super(MainActivity.class);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void setUp() throws Exception {
		// TODO Auto-generated method stub
		super.setUp();
		mStartIntent = new Intent(Intent.ACTION_MAIN);
	}

	@Override
	protected void tearDown() throws Exception {
		// TODO Auto-generated method stub
		super.tearDown();

	}

	@MediumTest
	public void testButtonClick() {

		startActivity(mStartIntent, null, null);
		TextView mTestMessage = (TextView)getActivity().findViewById(com.app.jnuit.R.id.txtView1);
		Button mTestButton = (Button) getActivity().findViewById(com.app.jnuit.R.id.btnSubmit);
		
		assertNotNull(getActivity());
		assertNotNull(mTestButton);
		assertNotNull(mTestMessage);

		//perform button click
		mTestButton.performClick();
		final String msg = mTestMessage.getText().toString();
		
		//check if text of TextView has changed
		if(msg.equalsIgnoreCase("button clicked")){

			assertTrue("text changed", true);
			
			//check if activity is finish or finish() is called
			assertTrue(isFinishCalled());
		}
				
	}

}

Finally, save all changes and run the test project. If the test cases are successful then you should see the following output!

testcase_output

That’s it for this tutorial. Hope it helps! 🙂

Reference: Android Testing