Friday 28 March 2014

Understanding MRAID


MRAID is an industry standard API for rich media ads running in mobile applications (http://www.iab.net/mraid). It provides banner ads with a standard way to expand/collapse banners and handle other situations that are not possible in a mobile application environment.

Inheritance







mraid
 

Constructor

mraid()

Instance Methods

Defined in mraid

close()
Downgrades the state of the ad. It will also fire the stateChange event.
  • For ads in an expanded state, close causes the StateType to transition to the default state.
  • This method may be used by ad designers as an addition to the SDK-enforced close ability.

Enumerations

Mobile Rich Media Ad Interface Definitions (MRAID)

MRAID, or “Mobile Rich Media Ad Interface Definitions” is the IAB Mobile Marketing Center of Excellence’s project to define a common API (Application Programming Interface) for mobile rich media ads that will run in mobile apps.  This is a standardized set of commands, designed to work with HTML5 and JavaScript, that developers creating rich media ads will use to communicate what those ads do (expand, resize, get access to device functionalities such as the accelerometer, etc) with the apps they are being served into.

Today different apps (incorporating different rich media vendors’ SDKs) have disparate requirements in terms of the APIs that creative developers must use to communicate with the app.  Therefore, the same creative has to have its code rewritten in order to run across different apps.  Developing a single API that diverse SDK vendors will support is the goal of MRAID.

This means that MRAID compliant rich media ads will run within MRAID compliant applications from any publisher using an MRAID compliant SDK. Put another way, agencies will be able to quickly and easily run creative across applications from different publishers.

Step by Step Executing android NDK Programs in ubuntu 11.40(Linux)

USE OF NDK:
The Android NDK is a companion tool to the Android SDK that lets you build performance-critical portions of your apps in native code. It provides headers and libraries that allow you to build activities, handle user input, use hardware sensors, access application resources, and more, when programming in C or C++. If you write native code, your applications are still packaged into an .apk file and they still run inside of a virtual machine on the device. The fundamental Android application model does not change.
Using native code does not result in an automatic performance increase, but always increases application complexity. If you have not run into any limitations using the Android framework APIs, you probably do not need the NDK.


Requirement to Execute the NDK Programs:
1. android sdk
2. android ndk-r7
You can download ndk from
link:http://developer.android.com/sdk/ndk/index.html
Download:android-ndk-r7-linux-x86.tar.bz2
3.setup the sdk in eclipse.


Steps to excecute the NDK:


Step1: Crete a android project in eclipse Eg:NDK



Step 2: Create the folder in our project name jni .and don't create the libs and obj folder in project those are automatically generated by ndk tool
Step 3: create a package in src in my case /NDK/src/com.srikanth


Step 4:creating a NativeCode class writing native methods: /NDK/src/com/srikanth/NativeCode.java

package com.srikanth;

public class NativeCode {

static {
System.loadLibrary("ndk_demo");
}

/**
* Adds two integers, returning their sum
*/
public native int add( int v1, int v2 );

/**
* Returns Hello World string
*/
public native String hello();

}

step5:
native method C file generator
using javah tool

Eecuting the NativeCode class using javah.Go to Terminal>
>cd goto your project direcotry
NDK>cd bin/classes
classes>javah -jni com.srNativeCode
the javah toll genrate the com_srikanth_NativeCode.h in classes folder copy the file in project jni folder. (NDK/jni/com_srikanth_NativeCode.h)

it look like below:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_srikanth_NativeLib */

#ifndef _Included_com_srikanth_NativeCode
#define _Included_com_srikanth_NativeCode
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_srikanth_NativeLib
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_srikanth_NativeCode_add
(JNIEnv *, jobject, jint, jint);

/*
* Class: com_srikanth_NativeLib
* Method: hello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_srikanth_NativeCode_hello
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif




step 6: Providing the native methods definition in ndk_demo.c file under NDK/jni/ndk_demo.c

#include "com_srikanth_NativeCode.h"

JNIEXPORT jstring JNICALL Java_com_srikanth_NativeCode_hello
(JNIEnv * env, jobject obj) {
return (*env)->NewStringUTF(env, "Hello World!");
}

JNIEXPORT jint JNICALL Java_com_srikanth_NativeCode_add
(JNIEnv * env, jobject obj, jint value1, jint value2) {
return (value1 + value2);
}


Step 7: Creating making file under jni dir (ie.NDK/jni/Android.mk)
Android.mk code


LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ndk_demo
LOCAL_SRC_FILES := ndk_demo.c

include $(BUILD_SHARED_LIBRARY)


Step 8:Building the ndk. Downloaded ndk extrace in any directory .My case ie in /home/android/android-ndk-r7. Goto the android-ndk-r7/prebuild/linu-x86/bin
under you can find file awk cheange the name to awk_


Step 9:
open terminal

> cd Projectdir
NDK>/home/android/android-ndk-r7/ndk-build

you will get the follwing file in your project

Compile thumb : ndk_demo <= ndk_demo.c

SharedLibrary : libndk_demo.so

Install : libndk_demo.so => libs/armeabi/libndk_demo.so


Refresh the project one ndk tool buld the folling folder and file (libs,obj)

step 10:creting ui for test this ndk. main.xml (/NDK/res/layout/main.xml)



Step 11:
NDKAcitive.java (/NDK/src/com/srikanth/NDKActivity.java)
package com.srikanth;

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

public class NDKActivity extends Activity {
/** Called when the activity is first created. */
NativeCode nativeLib;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nativeLib = new NativeCode();
String helloText = nativeLib.hello();

// Update the UI
TextView outText = (TextView) findViewById(R.id.textOut);
outText.setText(helloText);

// Setup the UI
Button buttonCalc = (Button) findViewById(R.id.buttonCalc);

buttonCalc.setOnClickListener(new OnClickListener() {
TextView result = (TextView) findViewById(R.id.result);
EditText value1 = (EditText) findViewById(R.id.value1);
EditText value2 = (EditText) findViewById(R.id.value2);

public void onClick(View v) {
int v1, v2, res = -1;
v1 = Integer.parseInt(value1.getText().toString().trim());
v2 = Integer.parseInt(value2.getText().toString().trim());

res = nativeLib.add(v1, v2);
result.setText(new Integer(res).toString());
}



});
}
}

Step 12:
Run the NDK Project

Thursday 27 March 2014

Content Provider

Content Providers are again one of the fundamental building blocks of the Android Platform. So far, we have looked at Activities, Services, which are basic building blocks. We have also looked at intents, notifications and variations of the same. None of these have dealt with stored data. Content Provider brings us to the concept of how to deal with data stored in the Android mobile esp. if the data has to be shared across applications.

Before we move on to shared data, let us understand the basics of data storage support provided by Android.

There are 4 ways we can store data:

    1.    Preferences
    2.    Files
    3.    RDBMS (SQLite)
    4.    Network


Preferences – Preferences are used to store user preferences for a single application or across applications in a mobile. They are typically name-value pairs accessible to the context.

Files – Files can be stored directly on to the mobile or to extended storage mediums. They are by default not accessible to applications other than the one that created it.

Database (RDBMS) – Android support creation of databases based on SQLite. These are again private to the application that created it.

Network – Android provides API support to store data over the network on to a server, probably
Note that all these are various forms of storing data and most often for a single application. Irrespective of how data is stored, if it has to be shared across applications, Here comes the concept of Content Providers.

Content Providers are the only way to share data across Android applications. They store and retrieve data thus making it accessible to all. Android platform provides default implementations of content providers for data types like audio, video, images, contact information etc.

In the sample I would like to first show how to work with existing content providers like the contact information. We will first view the existing contacts on the phone. We will insert a new contact (hardcoded name and phone number), update the same contact and delete the same contact, in this example. Note that the update and delete will not work till we create a contact through this example.

Introduction to Content Providers:

Irrespective of how the data is stored, Content Providers give a uniform interface to access the data. Data is exposed as a simple table with rows and columns where row is a record and column is a particular data type with a specific meaning. Like a row could be about a single person and the columns could be the person’s first name, number, address, email id etc.

Each record is identified by a unique _ID field which is the key to the record. Each content provider exposes a unique URI that identifies its data set uniquely. This URI is equivalent to a table name in a database. The URI consists of various parts: eg: content://com.colllabera.labs.sai/tasks/123 is a unique URI. content:// is a standard prefix. com.collabera.labs.sai is the authority, tasks is the table name, 123 is the unique _ID.

For the native content providers, these unique URIs are declared as constants in an interface. So, in our program we will be using constants like People.CONTENT_URI which internally translates to content://contacts/people

Let us now look at the code to view all the existing contacts:

//Here is the button to click for viewing the contacts
Button view = (Button)findViewById(R.id.viewButton);
//The method / class that gets invoked when the View button is clicked
view.setOnClickListener(new OnClickListener() {
    public void onClick(View v){
       displayContacts();
       Log.i("NativeContentProvider", "Completed Displaying Contact list");
    }
});
//Here is the displayContacts() method
private void displayContacts() {
      String[] columns = new String[] {People.NAME,People.NUMBER};
      Uri mContacts = People.CONTENT_URI;
      Cursor mCur = managedQuery(mContacts, // Contact URI
                  columns,    // Which columns to return
                  null,       // Which rows to return
                  null,       // Where clause parameters
                  null        // Order by clause
                  );
      if (mCur.moveToFirst()) {
            String name = null;
            String phoneNo = null;
            do {
              name = mCur.getString(mCur.getColumnIndex(People.NAME));
              phoneNo = mCur.getString(mCur.getColumnIndex(People.NUMBER));
              Toast.makeText(NativeContentProvider.this, name + " " + phoneNo, Toast.LENGTH_SHORT).show();
            } while (mCur.moveToNext());
      }
}

Here we are using the Activity.managedQuery(..) to create and execute a query against the provided URI. The comments against the parameters in the code is self-explanatory. This returns a cursor object that can be iterated using the two methods moveToFirst() and moveToNext(). For simplicity sake, I have just toasted the contact name and phone number retrieved. An advanced tutorial can start a new activity that can display this in a ListView.

Now, we can move on to creating a new contact. While the button related code will be very similar to the above, let us look at the actual createContact() method.

private void createContact(String name, String phone) {
      ContentValues contact = new ContentValues();
      contact.put(People.NAME, name);
      insertUri = getContentResolver().insert(People.CONTENT_URI, contact);
      Log.d(getClass().getSimpleName(),insertUri.toString());
      Uri phoneUri = Uri.withAppendedPath(insertUri, People.Phones.CONTENT_DIRECTORY);
      contact.clear();
      contact.put(People.Phones.TYPE, People.TYPE_MOBILE);
      contact.put(People.NUMBER, phone);
      updateUri = getContentResolver().insert(phoneUri, contact);
      Toast.makeText(NativeContentProvider.this, "Created a new contact: " + name + " " + phone, Toast.LENGTH_SHORT).show();
      Log.d(getClass().getSimpleName(),updateUri.toString());
    }
 
Here we need to understand 2 new classes: ContentResolver and ContentValues. A ContentResolver provides applications access to the content data / model. We can get a handle to a ContentResolver by calling the getContentResolver() method within the Activity. This provides methods to insert, update and delete data. In order to insert data, we need to provide it through a ContentValues object. A ContentValues Object is nothing but a name, value pair where the name of the column is to be mentioned. So, we pass the URI and the ContentValues to insert() method which returns a unique URI with the new ID created. Once we get the ID of the new person/contact inserted, we insert his/her mobile phone details into the related Phones table by using the returned insertUri. The insertUri which is unique to the new record is stored as a class variable to use it in the delete method later. The phoneUri is also stored for updating the same in the updateContact() method later.

Note that People is a class that has implemented various interfaces like android.priovider.BaseColumns, android.provider.Contacts.Phones, android.provider.Contact.PeopleColumns etc. These constants come from the interfaces.

With the above understanding let us see the update and delete methods:

private void updateContact(String phone) {
      if (updateUri == null) {
            Toast.makeText(NativeContentProvider.this, "There is nothing to update, Please create a contact and then click update", Toast.LENGTH_LONG).show();
      } else {
            ContentValues newPhone = new ContentValues();
            newPhone.put(People.Phones.TYPE, People.TYPE_MOBILE);
            newPhone.put(People.NUMBER, phone);
            getContentResolver().update(updateUri, newPhone, null,null);
            Toast.makeText(NativeContentProvider.this, "Updated the phone number to: " + phone, Toast.LENGTH_SHORT).show();
            Log.i(getClass().getSimpleName(), "Updated the phone number");
      }
    }
   
    private void deleteContact() {
      if (updateUri == null) {
            Toast.makeText(NativeContentProvider.this, "Please create a contact by clicking create button, then I can delete the same", Toast.LENGTH_LONG).show();
           
      } else {
            getContentResolver().delete(insertUri, null, null);
            Toast.makeText(NativeContentProvider.this, "Deleted contact at: " + insertUri.toString(), Toast.LENGTH_SHORT).show();
            updateUri = null;
            insertUri = null;
            Log.i(getClass().getSimpleName(),"Deleted the contact inserted by this program");
      }
    }


These methods only manipulate the freshly created record, for simplicity sake. They call upon the update() and delete() method on the ContentResolver.

The complete code for this example is available here.

Please note that you must add the following permissions to the AndroidManifest.xml file to be able to access the contacts.
 
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>

Otherwise you get a SecurityException.
 

Thursday 6 March 2014

Android Broadcast Receivers

Broadcast Receivers simply respond to broadcast messages from other applications or from the system itself. These messages are sometime called events or intents. For example, applications can also initiate broadcasts to let other applications know that some data has been downloaded to the device and is available for them to use, so this is broadcast receiver who will intercept this communication and will initiate appropriate action.

There are following two important steps to make BroadcastReceiver works for the systen broadcasted intents:

    Creating the Broadcast Receiver.

    Registering Broadcast Receiver

There is one additional steps in case you are going to implement your custom intents then you will have to create and broadcast those intents.


Creating the Broadcast Receiver

A broadcast receiver is implemented as a subclass of BroadcastReceiver class and overriding the onReceive() method where each message is received as a Intent object parameter.

public class MyReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {
      Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
   }

}

Registering Broadcast Receiver

An application listens for specific broadcast intents by registering a broadcast receiver in AndroidManifest.xml file. Consider we are going to register MyReceiver for system generated event ACTION_BOOT_COMPLETED which is fired by the system once the Android system has completed the boot process.

<application
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name"
   android:theme="@style/AppTheme" >

   <receiver android:name="MyReceiver">
      <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED">
      </action>
      </intent-filter>
   </receiver>

</application>

Now whenever your Android device gets booted, it will be intercepted by BroadcastReceiver MyReceiver and implemented logic inside onReceive() will be executed.

There are several system generated events defined as final static fields in the Intent class. The following table lists a few important system events.
Event Constant    Description
android.intent.action.BATTERY_CHANGED    Sticky broadcast containing the charging state, level, and other information about the battery.
android.intent.action.BATTERY_LOW    Indicates low battery condition on the device.
android.intent.action.BATTERY_OKAY    Indicates the battery is now okay after being low.
android.intent.action.BOOT_COMPLETED    This is broadcast once, after the system has finished booting.
android.intent.action.BUG_REPORT    Show activity for reporting a bug.
android.intent.action.CALL    Perform a call to someone specified by the data.
android.intent.action.CALL_BUTTON    The user pressed the "call" button to go to the dialer or other appropriate UI for placing a call.
android.intent.action.DATE_CHANGED    The date has changed.
android.intent.action.REBOOT    Have the device reboot.
Broadcasting Custom Intents

If you want your application itself should generate and send custom intents then you will have to create and send those intents by using the sendBroadcast() method inside your activity class. If you use the sendStickyBroadcast(Intent) method, the Intent is sticky, meaning the Intent you are sending stays around after the broadcast is complete.

public void broadcastIntent(View view)
{
   Intent intent = new Intent();
   intent.setAction("com.tutorialspoint.CUSTOM_INTENT");
   sendBroadcast(intent);
}

This intent com.tutorialspoint.CUSTOM_INTENT can also be regsitered in similar way as we have regsitered system generated intent.

<application
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name"
   android:theme="@style/AppTheme" >

   <receiver android:name="MyReceiver">
      <intent-filter>
         <action android:name="com.tutorialspoint.CUSTOM_INTENT">
      </action>
      </intent-filter>
   </receiver>

</application>

Example

This example will explain you how to create BroadcastReceiver to intercept custom intent. Once you are familiar with custom intent, then you can program your application to intercept system generated intents. So let's follow the following steps to modify the Android application we created in Hello World Example chapter:
Step    Description
1    You will use Eclipse IDE to create an Android application and name it as HelloWorld under a package com.example.helloworld as explained in the Hello World Example chapter.
2    Modify main activity file MainActivity.java to add broadcastIntent() method.
3    Create a new java file called MyReceiver.java under the package com.example.helloworld to define a BroadcastReceiver.
4    An application can handle one or more custom and system intents without any restrictions. Every indent you want to intercept must be registered in your AndroidManifest.xml file using <receiver.../> tag
5    Modify the detault content of res/layout/activity_main.xml file to include a button to broadcast intent.
6    Define a constant broadcast_intent in res/values/strings.xml file
7    Run the application to launch Android emulator and verify the result of the changes done in the aplication.

Following is the content of the modified main activity file src/com.example.helloworld/MainActivity.java. This file can include each of the fundamental lifecycle methods. We have added broadcastIntent() method to broadcast a custom intent.

package com.example.helloworld;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.content.Intent;
import android.view.View;

public class MainActivity extends Activity {

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.activity_main, menu);
      return true;
   }
   // broadcast a custom intent.
   public void broadcastIntent(View view)
   {
      Intent intent = new Intent();
      intent.setAction("com.tutorialspoint.CUSTOM_INTENT");
      sendBroadcast(intent);
   }
}

Following is the content of src/com.example.helloworld/MyReceiver.java:

package com.example.helloworld;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {
      Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
   }

}

Following will the modified content of AndroidManifest.xml file. Here we have added <service.../> tag to include our service:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.helloworld"
   android:versionCode="1"
   android:versionName="1.0" >
   <uses-sdk
      android:minSdkVersion="8"
      android:targetSdkVersion="15" />
   <application
       android:icon="@drawable/ic_launcher"
       android:label="@string/app_name"
       android:theme="@style/AppTheme" >
       <activity
           android:name=".MainActivity"
           android:label="@string/title_activity_main" >
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER"/>
           </intent-filter>
       </activity>
       <receiver android:name="MyReceiver">
          <intent-filter>
          <action android:name="com.tutorialspoint.CUSTOM_INTENT">
          </action>
          </intent-filter>
      </receiver>
   </application>
</manifest>

Following will be the content of res/layout/activity_main.xml file to include a button to broadcast our custom intent:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >

   <Button android:id="@+id/btnStartService"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/broadcast_intent"
   android:onClick="broadcastIntent"/>

</LinearLayout>

Following will be the content of res/values/strings.xml to define two new constants:

<resources>

    <string name="app_name">HelloWorld</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">MainActivity</string>
    <string name="broadcast_intent">Broadcast Intent</string>

</resources>

 For More Details

For instance, a Broadcast receiver triggers battery Low notification that you see on your mobile screen.

Other instances caused by a Broadcast Receiver are new friend notifications, new friend feeds, new message etc. on your Facebook app.

In fact, you see broadcast receivers at work all the time. Notifications like incoming messages, WiFi Activated/Deactivated message etc. are all real-time announcements of what is happening in the Android system and the applications


Consider this:

You have an important social gathering to attend. Because of your shoddy memory, you have requested your friend to notify you a day before the event. Now, because you have ‘registered’ for the said friend’s help, you will get a reminder from him as discussed. This is roughly how the Broadcast Receiver works.

We have also discussed an example at the end of this Android Tutorial (in the example, a notification is generated once the system time is changed).
How important is it to implement Broadcast Receivers correctly?

If you wish to create a good Android application, this is of utmost importance. If the broadcast events do not perform their job (of sending notifications to support the application’s primary task) perfectly, the application would not be intuitive and user friendly.
Registration of Broadcast Receiver

There are two ways to register a Broadcast Receiver; one is Static and the other Dynamic.

1)      Static: Use <receiver> tag in your Manifest file. (AndroidManifest.xml)

2)      Dynamic: Use Context.registerReceiver () method to dynamically register an instance.
Classes of Broadcasts

The two major classes of broadcasts are:

1)  Ordered Broadcasts: These broadcasts are synchronous, and therefore follow a specific order. The order is defined using android: priority attribute. The receivers with greater priority would receive the broadcast first. In case there are receivers with same priority levels, the broadcast would not follow an order. Each receiver (when it receives the broadcast) can either pass on the notification to the next one, or abort the broadcast completely. On abort, the notification would not be passed on to the receivers next in line.

2)  Normal Broadcasts: Normal broadcasts are not orderly. Therefore, the registered receivers often run all at the same time. This is very efficient, but the Receivers are unable to utilize the results.

Sometimes to avoid system overload, the system delivers the broadcasts one at a time, even in case of normal broadcasts. However, the receivers still cannot use the results.
Difference between Activity Intent and Broadcasting Intent

You must remember that Broadcasting Intents are different from the Intents used to start an Activity or a Service (discussed in previous Android Tutorials). The intent used to start an Activity makes changes to an operation the user is interacting with, so the user is aware of the process. However, in case of broadcasting intent, the operation runs completely in the background, and is therefore invisible to the user.
Implementing the Broadcast Receiver

You need to follow these steps to implement a broadcast receiver:

1)      Create a subclass of Android’s BroadcastReceiver

2)      Implement the onReceive() method: In order for the notification to be sent, an onReceive() method has to be implemented. Whenever the event for which the receiver is registered occurs, onReceive() is called. For instance, in case of battery low notification, the receiver is registered to Intent.ACTION_BATTERY_LOW event. As soon as the battery level falls below the defined level, this onReceive() method is called.

Following are the two arguments of the onReceive() method:

    Context: This is used to access additional information, or to start services or activities.
    Intent: The Intent object is used to register the receiver.

Security

As the broadcast receivers have a global work-space, security is very important concern here. If you do not define the limitations and filters for the registered receivers, other applications can abuse them.
Here are a few limitations that might help:

    Whenever you publish a receiver in your application’s manifest, make it unavailable to external applications by using android: exported=”false”. You might think that specifying Intent filters while publishing the receiver would do the task for you, when in reality they are not enough.
    When you send a broadcast, it is possible for the external applications too to receive them. This can be prevented by specifying a few limitations.
    Similarly, when you register your receiver using registerReceiver, any application may send it broadcasts. This can be prevented using permissions as well.

(PS: As of Android 3.1, the Android system will not receive any external Intent, so the system is comparatively secure now.)

Prolonged Operations

The Broadcast Receiver object is active only for the duration of onReceive (Context, Intent).
Therefore, if you need to allow an action after receiving the notification services should be triggered, and not broadcast receivers.

    To show a dialogue, then you should use NotificationManager API
    If you wish to send a broadcast intent that would stick around even after the broadcast is complete, you must use sendStickyBroadcast (Intent) method.

Broadcast Receiver Example

In this sample application, a notification is generated when you change the system time. The notification when clicked leads the user to the Contacts. This is how the application works: