Show Download Progress in NotificationBar in Android with Notification Event Listeners

Below Sample code shows you how to download images from a url with progress in the notification bar.

Notification Access Download

package com.coderzheaven.customnotificationdownloaddemo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;

public class MainActivity extends ActionBarActivity {

	NotificationCompat.Builder mBuilder;
	NotificationManager mNotifyManager;
	int id = 1;
	String urlsToDownload[] = { "http://www.devoxx.be/wp-content/uploads/2014/10/android.png", "http://www.devoxx.be/wp-content/uploads/2014/10/android.png",
			"http://www.devoxx.be/wp-content/uploads/2014/10/android.png", "http://www.devoxx.be/wp-content/uploads/2014/10/android.png",
			"http://www.devoxx.be/wp-content/uploads/2014/10/android.png" };
	int counter = 0;
	private NotificationReceiver nReceiver;
	ArrayList<AsyncTask<String, String, Void>> arr;

	class NotificationReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			String event = intent.getExtras().getString(NLService.NOT_EVENT_KEY);
			Log.i("NotificationReceiver", "NotificationReceiver onReceive : " + event);
			if (event.trim().contentEquals(NLService.NOT_REMOVED)) {
				killTasks();
			}
		}
	}

	private void killTasks() {
		if (null != arr & arr.size() > 0) {
			for (AsyncTask<String, String, Void> a : arr) {
				if (a != null) {
					Log.i("NotificationReceiver", "Killing download thread");
					a.cancel(true);
				}
			}
			mNotifyManager.cancelAll();
		}
	}

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

		mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		mBuilder = new NotificationCompat.Builder(this);
		mBuilder.setContentTitle("Downloading images...").setContentText("Download in progress").setSmallIcon(R.drawable.ic_launcher);
		// Start a lengthy operation in a background thread
		mBuilder.setProgress(0, 0, true);
		mNotifyManager.notify(id, mBuilder.build());
		mBuilder.setAutoCancel(true);

		arr = new ArrayList<AsyncTask<String, String, Void>>();
		int incr;
		for (incr = 0; incr < urlsToDownload.length; incr++) {
			ImageDownloader imageDownloader = new ImageDownloader();
			imageDownloader.execute(urlsToDownload[incr]);
			arr.add(imageDownloader);
		}

		ContentResolver contentResolver = getContentResolver();
		String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
		String packageName = getPackageName();

		// check to see if the enabledNotificationListeners String contains our
		// package name
		if (enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName)) {
			// in this situation we know that the user has not granted the app
			// the Notification access permission
			// Check if notification is enabled for this application
			Log.i("ACC", "Dont Have Notification access");
			Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
			startActivity(intent);
		} else {
			Log.i("ACC", "Have Notification access");
		}

		nReceiver = new NotificationReceiver();
		IntentFilter filter = new IntentFilter();
		filter.addAction(NLService.NOT_TAG);
		registerReceiver(nReceiver, filter);

	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		killTasks();
		unregisterReceiver(nReceiver);
	}

	private void downloadImagesToSdCard(String downloadUrl, String imageName) {
		FileOutputStream fos;
		InputStream inputStream = null;

		try {
			URL url = new URL(downloadUrl);
			/* making a directory in sdcard */
			String sdCard = Environment.getExternalStorageDirectory().toString();
			File myDir = new File(sdCard, "DemoDownload");

			/* if specified not exist create new */
			if (!myDir.exists()) {
				myDir.mkdir();
				Log.v("", "inside mkdir");
			}

			/* checks the file and if it already exist delete */
			String fname = imageName;
			File file = new File(myDir, fname);
			Log.d("file===========path", "" + file);
			if (file.exists())
				file.delete();

			/* Open a connection */
			URLConnection ucon = url.openConnection();

			HttpURLConnection httpConn = (HttpURLConnection) ucon;
			httpConn.setRequestMethod("GET");
			httpConn.connect();
			inputStream = httpConn.getInputStream();

			/*
			 * if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
			 * inputStream = httpConn.getInputStream(); }
			 */

			fos = new FileOutputStream(file);
			// int totalSize = httpConn.getContentLength();
			// int downloadedSize = 0;
			byte[] buffer = new byte[1024];
			int bufferLength = 0;
			while ((bufferLength = inputStream.read(buffer)) > 0) {
				fos.write(buffer, 0, bufferLength);
				// downloadedSize += bufferLength;
				// Log.i("Progress:", "downloadedSize:" + downloadedSize +
				// "totalSize:" + totalSize);
			}
			inputStream.close();
			fos.close();
			Log.d("test", "Image Saved in sdcard..");
		} catch (IOException io) {
			inputStream = null;
			fos = null;
			io.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {

		}

	}

	private class ImageDownloader extends AsyncTask<String, String, Void> {

		@Override
		protected Void doInBackground(String... param) {
			downloadImagesToSdCard(param[0], "Image" + counter + ".png");
			return null;
		}

		protected void onProgressUpdate(String... values) {
		}

		@Override
		protected void onPreExecute() {
			Log.i("Async-Example", "onPreExecute Called");
		}

		@Override
		protected void onPostExecute(Void result) {
			Log.i("Async-Example", "onPostExecute Called");

			float len = urlsToDownload.length;
			// When the loop is finished, updates the notification
			if (counter >= len - 1) {
				mBuilder.setContentTitle("Done.");
				mBuilder.setContentText("Download complete")
				// Removes the progress bar
						.setProgress(0, 0, false);
				mNotifyManager.notify(id, mBuilder.build());
			} else {
				int per = (int) (((counter + 1) / len) * 100f);
				Log.i("Counter", "Counter : " + counter + ", per : " + per);
				mBuilder.setContentText("Downloaded (" + per + "/100");
				mBuilder.setProgress(100, per, false);
				// Displays the progress bar for the first time.
				mNotifyManager.notify(id, mBuilder.build());
			}
			counter++;

		}

	}
}

“NLService” Class is the actual Notification Listener class that can hear events in your notification.
But before everything you need to be sure that, you have enabled notification access for your app.

package com.coderzheaven.customnotificationdownloaddemo;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;

@SuppressLint("NewApi")
public class NLService extends NotificationListenerService {
	private String TAG = this.getClass().getSimpleName();
	public static final String NOT_TAG = "com.coderzheaven.NOTIFICATION_LISTENER";
	public static final String NOT_POSTED = "POSTED";
	public static final String NOT_REMOVED = "REMOVED";
	public static final String NOT_EVENT_KEY = "not_key";

	@Override
	public void onCreate() {
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	@Override
	public void onNotificationPosted(StatusBarNotification sbn) {
		Log.i(TAG, "**********  onNotificationPosted");
		Intent i = new Intent(NOT_TAG);
		i.putExtra(NOT_EVENT_KEY, NOT_POSTED);
		sendBroadcast(i);
	}

	@Override
	public void onNotificationRemoved(StatusBarNotification sbn) {
		Log.i(TAG, "********** onNOtificationRemoved");
		Intent i = new Intent(NOT_TAG);
		i.putExtra(NOT_EVENT_KEY, NOT_REMOVED);
		sendBroadcast(i);
	}

}

Make sure you add the “services” in the AndroidManifest file.

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="22" />

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name="com.coderzheaven.customnotificationdownloaddemo.NLService"
            android:label="@string/app_name"
            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
            <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
        </service>
    </application>

</manifest>

You can download the complete source code from here..

How to find your Google Plus ID

This is so simple

1. Go to your Google + account (https://plus.google.com/).

2. Click on the Profile icon on the Left.

3. If you look at the URL in the address bar, it should look something like this:

https://plus.google.com/104653270154306099169/posts

4. The long numerical string in the URL is your Google+ ID. Here is CoderzHeaven’s from the URL above:

104653270154306099169/

Google + CoderzHeaven

How will you create a custom Notification in Android with a custom Layout?

This sample application does that.

First create an xml for your notification.

custom_notification.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp" >
    <ImageView android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_marginRight="10dp" />
    <TextView android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        style="Custom Notification Title" />
    <TextView android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        android:layout_below="@id/title"
        style="Custom Notification Text" />
</RelativeLayout>

Now the java code.

package com.coderzheaven.customnotification;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.widget.RemoteViews;

public class MainActivity extends Activity {

    @SuppressWarnings("deprecation")
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        int icon = R.drawable.ic_launcher;
        long when = System.currentTimeMillis();
        Notification notification = new Notification(icon, "Custom Notification", when);

    	NotificationManager mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    	
        RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification);
        contentView.setImageViewResource(R.id.image, R.drawable.ic_launcher);
        contentView.setTextViewText(R.id.title, "Custom notification");
        contentView.setTextViewText(R.id.text, "This is a custom layout");
        notification.contentView = contentView;
        
        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        notification.contentIntent = contentIntent;
        
        notification.flags |= Notification.FLAG_NO_CLEAR; //Do not clear the notification
        notification.defaults |= Notification.DEFAULT_LIGHTS; // LED
        notification.defaults |= Notification.DEFAULT_VIBRATE; //Vibration
        notification.defaults |= Notification.DEFAULT_SOUND; // Sound
        
        mNotificationManager.notify(1, notification);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

Custom Notification

Send Data when Clicking on a Notification in Android?

Hello everyone…

I have shown in my previous tutorials on how to create notification in android and cancel it.
This is the post showing this .

Now today I am going to show how to send data when you click on the notification message.

Here I am creating two activities. One the main activity that creates the notification and the other one is used when you click on the notification.
i.e the second activity is called when you click on the notification.

Here is the main activity that sends the notification.

java source code.

NotificationDemo .java

package com.coderzheaven.pack;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class NotificationDemo extends Activity implements View.OnClickListener{
	private Button buttonSend, clear;
	private static final int NOT_ID = 1;

	@Override
	public void onCreate(Bundle savedInstanceState) {

	  super.onCreate(savedInstanceState);
	  setContentView(R.layout.main);
	  buttonSend = (Button) this.findViewById( R.id.send);
	  clear = (Button) this.findViewById( R.id.cancel);
	  buttonSend.setOnClickListener(this);
	  clear.setOnClickListener(this);

	}

	@Override
	public void onClick(View v) {
		String ns = Context.NOTIFICATION_SERVICE;
	 	NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);

		if(v == buttonSend){
	 		int icon = R.drawable.icon;
	 		CharSequence tickerText = "Hello ";
	 		long when = System.currentTimeMillis();

	 		int requestID = (int) System.currentTimeMillis();
	 		Notification notification = new Notification(icon, tickerText, when);
	 		Context context = getApplicationContext();
	 		Intent notificationIntent = new Intent(this, GoToNotification.class);
	 		notificationIntent.putExtra("data1", "My Data 1");
	 		notificationIntent.putExtra("data2", "My Data 2");
	 		notificationIntent.setAction("myString"+ requestID);
			PendingIntent contentIntent = PendingIntent.getActivity(this, requestID, notificationIntent, 0);
			notificationIntent.setData((Uri.parse("mystring"+requestID)));
	    	        notification.setLatestEventInfo(context, "Notification Demo", requestID + "", contentIntent);
        	    	notification.flags += Notification.FLAG_ONGOING_EVENT;
        	    	notification.flags += Notification.FLAG_AUTO_CANCEL;
	        	mNotificationManager.notify(NOT_ID, notification);
		}else{
			Toast.makeText(getApplicationContext(),"Cancelling", Toast.LENGTH_SHORT).show();
			mNotificationManager.cancel(NOT_ID);
		}

	}
}

The main.xml that creates the layout for the above activity.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
<Button
	android:text="Send Notification"
	android:id="@+id/send"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content">
</Button>
<Button
	android:text="Cancel Notification"
	android:id="@+id/cancel"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content">
</Button>
</LinearLayout>

Now the second activity that is called when you click on the notification.

package com.coderzheaven.pack;

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

public class GoToNotification extends Activity{

	TextView tv = null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		System.out.println("onCreate");

		setContentView(R.layout.notification);
		tv = (TextView)findViewById(R.id.tv);

		Bundle extras = getIntent().getExtras();

		if(extras != null){
			String data1 = extras.getString("data1");
			String data2 = extras.getString("data2");
			System.out.println("Ddata1 : " + data1);
			tv.setText("Data Sent from Clicking Notification nData 1 : " + data1 + "nData 2 : " + data2);
		}
	}

}

This is the layout for the second activity.
It simply contains a textview to show the passed data.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    android:id="@+id/tv"
    />

</LinearLayout>

Also declare the activity in the manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.coderzheaven.pack"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".NotificationDemo"
                  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=".GoToNotification"
                  android:label="@string/app_name" />
    </application>
</manifest>

Download the complete source code here.

Please leave your valuable comments.

Using NotificationManager in ANDROID for showing notification, sample code.

Multiple Notifications are a unique feature in ANDROID phones. This tutorial will show you how to create notification from your application.
ANDROID uses the NotificationManager class to create the notification.
Let’s look at the code.

package com.Webviews;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class NotificationActivity  extends Activity implements View.OnClickListener {

private Button button, clear;
private NotificationManager mManager;
private static final int APP_ID = 0;

@Override

public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  button = (Button) this.findViewById( R.id.my_button);
  clear = (Button) this.findViewById( R.id.cancel);
  clear.setOnClickListener(new OnClickListener() {

	@Override
	public void onClick(View arg0) {

		mManager.cancel(APP_ID);
	}
  });
  button.setOnClickListener(this);
  mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void onClick(View v) {

  Intent intent = new Intent(this,NotificationActivity.class);
  Notification notification = new Notification(R.drawable.icon,"Notification!!", System.currentTimeMillis());
  notification.setLatestEventInfo(NotificationActivity.this,"Send by which application","Description of the notification",
		  					      PendingIntent.getActivity(this.getBaseContext(), 0, intent,
		  					      PendingIntent.FLAG_NO_CREATE));
  mManager.notify(APP_ID, notification);
}
}

Explanation.

mManager.notify(APP_ID, notification);

This line in the code sends the notification where notification is the object of the Notification class where you can set the data and title for the notification.

This line will cancel the notification created by this application.

mManager.cancel(APP_ID);

The layout file for the above code “main.xml”

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />

<Button
	android:text="Send Notification"
	android:id="@+id/my_button"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content">
</Button>

<Button
	android:text="Cancel Notification"
	android:id="@+id/cancel"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content">
</Button>

</LinearLayout>

Please leave your valuable comments on this post.