Example of Content provider

30th July 2013,

src/com.example.mycontentprovider/MainActivity.java. This file can include each of the fundamental lifecycle methods. We have added two new methods onClickAddName() andonClickRetrieveStudents() to handle user interaction with the application.

package com.example.mycontentprovider;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

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

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

   public void onClickAddName(View view) {
      // Add a new student record
      ContentValues values = new ContentValues();

      values.put(StudentsProvider.NAME, 
      ((EditText)findViewById(R.id.txtName)).getText().toString());

      values.put(StudentsProvider.GRADE, 
      ((EditText)findViewById(R.id.txtGrade)).getText().toString());

      Uri uri = getContentResolver().insert(
      StudentsProvider.CONTENT_URI, values);

      Toast.makeText(getBaseContext(), 
      uri.toString(), Toast.LENGTH_LONG).show();
   }

   public void onClickRetrieveStudents(View view) {
      // Retrieve student records
      String URL = "content://com.example.provider.College/students";
      Uri students = Uri.parse(URL);
      Cursor c = managedQuery(students, null, null, null, "name");
      if (c.moveToFirst()) {
         do{
            Toast.makeText(this, 
            c.getString(c.getColumnIndex(StudentsProvider._ID)) + 
            ", " +  c.getString(c.getColumnIndex( StudentsProvider.NAME)) + 
            ", " + c.getString(c.getColumnIndex( StudentsProvider.GRADE)), 
            Toast.LENGTH_SHORT).show();
         } while (c.moveToNext());
      }
   }
}

Create new file StudentsProvider.java under com.example.mycontentprovider package and following is the content of src/com.example.mycontentprovider/StudentsProvider.java:

package com.example.mycontentprovider;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class StudentsProvider extends ContentProvider {

   static final String PROVIDER_NAME = "com.example.provider.College";
   static final String URL = "content://" + PROVIDER_NAME + "/students";
   static final Uri CONTENT_URI = Uri.parse(URL);

   static final String _ID = "_id";
   static final String NAME = "name";
   static final String GRADE = "grade";

   private static HashMap<String, String> STUDENTS_PROJECTION_MAP;

   static final int STUDENTS = 1;
   static final int STUDENT_ID = 2;

   static final UriMatcher uriMatcher;
   static{
      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
      uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS);
      uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID);
   }

   /**
    * Database specific constant declarations
    */
   private SQLiteDatabase db;
   static final String DATABASE_NAME = "College";
   static final String STUDENTS_TABLE_NAME = "students";
   static final int DATABASE_VERSION = 1;
   static final String CREATE_DB_TABLE = 
      " CREATE TABLE " + STUDENTS_TABLE_NAME +
      " (_id INTEGER PRIMARY KEY AUTOINCREMENT, " + 
      " name TEXT NOT NULL, " +
      " grade TEXT NOT NULL);";

   /**
    * Helper class that actually creates and manages 
    * the provider's underlying data repository.
    */
   private static class DatabaseHelper extends SQLiteOpenHelper {
       DatabaseHelper(Context context){
          super(context, DATABASE_NAME, null, DATABASE_VERSION);
       }

       @Override
       public void onCreate(SQLiteDatabase db)
       {
          db.execSQL(CREATE_DB_TABLE);
       }

       @Override
       public void onUpgrade(SQLiteDatabase db, int oldVersion, 
                             int newVersion) {
          db.execSQL("DROP TABLE IF EXISTS " +  STUDENTS_TABLE_NAME);
          onCreate(db);
       }
   }

   @Override
   public boolean onCreate() {
      Context context = getContext();
      DatabaseHelper dbHelper = new DatabaseHelper(context);
      /**
       * Create a write able database which will trigger its 
       * creation if it doesn't already exist.
       */
      db = dbHelper.getWritableDatabase();
      return (db == null)? false:true;
   }

   @Override
   public Uri insert(Uri uri, ContentValues values) {
      /**
       * Add a new student record
       */
      long rowID = db.insert(	STUDENTS_TABLE_NAME, "", values);
      /** 
       * If record is added successfully
       */
      if (rowID > 0)
      {
         Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
         getContext().getContentResolver().notifyChange(_uri, null);
         return _uri;
      }
      throw new SQLException("Failed to add a record into " + uri);
   }

   @Override
   public Cursor query(Uri uri, String[] projection, String selection,	
                       String[] selectionArgs, String sortOrder) {

      SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
      qb.setTables(STUDENTS_TABLE_NAME);

      switch (uriMatcher.match(uri)) {
      case STUDENTS:
         qb.setProjectionMap(STUDENTS_PROJECTION_MAP);
         break;
      case STUDENT_ID:
         qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1));
         break;
      default:
         throw new IllegalArgumentException("Unknown URI " + uri);
      }
      if (sortOrder == null || sortOrder == ""){
         /** 
          * By default sort on student names
          */
         sortOrder = NAME;
      }
      Cursor c = qb.query(db,	projection,	selection, selectionArgs, 
                          null, null, sortOrder);
      /** 
       * register to watch a content URI for changes
       */
      c.setNotificationUri(getContext().getContentResolver(), uri);

      return c;
   }

   @Override
   public int delete(Uri uri, String selection, String[] selectionArgs) {
      int count = 0;

      switch (uriMatcher.match(uri)){
      case STUDENTS:
         count = db.delete(STUDENTS_TABLE_NAME, selection, selectionArgs);
         break;
      case STUDENT_ID:
         String id = uri.getPathSegments().get(1);
         count = db.delete( STUDENTS_TABLE_NAME, _ID +  " = " + id + 
                (!TextUtils.isEmpty(selection) ? " AND (" + 
                selection + ')' : ""), selectionArgs);
         break;
      default: 
         throw new IllegalArgumentException("Unknown URI " + uri);
      }

      getContext().getContentResolver().notifyChange(uri, null);
      return count;
   }

   @Override
   public int update(Uri uri, ContentValues values, String selection, 
                     String[] selectionArgs) {
      int count = 0;

      switch (uriMatcher.match(uri)){
      case STUDENTS:
         count = db.update(STUDENTS_TABLE_NAME, values, 
                 selection, selectionArgs);
         break;
      case STUDENT_ID:
         count = db.update(STUDENTS_TABLE_NAME, values, _ID + 
                 " = " + uri.getPathSegments().get(1) + 
                 (!TextUtils.isEmpty(selection) ? " AND (" +
                 selection + ')' : ""), selectionArgs);
         break;
      default: 
         throw new IllegalArgumentException("Unknown URI " + uri );
      }
      getContext().getContentResolver().notifyChange(uri, null);
      return count;
   }

   @Override
   public String getType(Uri uri) {
      switch (uriMatcher.match(uri)){
      /**
       * Get all student records 
       */
      case STUDENTS:
         return "vnd.android.cursor.dir/vnd.example.students";
      /** 
       * Get a particular student
       */
      case STUDENT_ID:
         return "vnd.android.cursor.item/vnd.example.students";
      default:
         throw new IllegalArgumentException("Unsupported URI: " + uri);
      }
   }
}

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

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

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.mycontentprovider.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>
        <provider android:name="StudentsProvider" 
           android:authorities="com.example.provider.College">
        </provider>
    </application>

</manifest>

Following will be the content of res/layout/activity_main.xml file to include a button to broadcast your 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" >
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Name" />
    <EditText
    android:id="@+id/txtName"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent" />
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Grade" />
    <EditText
    android:id="@+id/txtGrade"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent" />
    <Button
    android:text="Add Name"
    android:id="@+id/btnAdd"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:onClick="onClickAddName" />
    <Button
    android:text="Retrieve Students"
    android:id="@+id/btnRetrieve"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:onClick="onClickRetrieveStudents" />
</LinearLayout>

Make sure you have following content of res/values/strings.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">MyContentProvider</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>

</resources>;

Let’s try to run our modified MyContentProvider application we just created. I assume you had created your AVD while doing environment setup. To run the app from Eclipse, open one of your project’s activity files and click Run Eclipse Run Icon icon from the toolbar. Eclipse installs the app on your AVD and starts it and if everything is fine with your setup and application, it will display following Emulator window, be patience because it may take sometime based on your computer speed:

Android Content Provider Demo

Now let’s enter student Name and Grade and finally click on Add Name button, this will add student record in the database and will flash a message at the bottom showing ContentProvider URI along with record number added in the database. This operation makes use of our insert() method. Let’s repeat this process to add few more students in the database of our content provider.

Add Records using ContentProvider

Once you are done with adding records in the database, now its time to ask ContentProvider to give us those records back, so let’s click Retrieve Students button which will fetch and display all the records one by one which is as per our the implementation of our query() method.

Fetch Records using ContentProvider

You can write activities against update and delete operations by providing callback functions inMainActivity.java file and then modify user interface to have buttons for update and deleted operations in the same way as we have done for add and read operations.

This way you can use existing Content Provider like Address Book or you can use Content Provider concept in developing nice database oriented applications where you can perform all sort of database operations like read, write, update and delete as explained above in the example.

Managing Audio Focus

With multiple apps potentially playing audio it’s important to think about how they should interact. To avoid every music app playing at the same time, Android uses audio focus to moderate audio playback—only apps that hold the audio focus should play audio.

Before your app starts playing audio it should request—and receive—the audio focus. Likewise, it should know how to listen for a loss of audio focus and respond appropriately when that happens.

Request the Audio Focus


Before your app starts playing any audio, it should hold the audio focus for the stream it will be using. This is done with a call to requestAudioFocus() which returns AUDIOFOCUS_REQUEST_GRANTED if your request is successful.

You must specify which stream you’re using and whether you expect to require transient or permanent audio focus. Request transient focus when you expect to play audio for only a short time (for example when playing navigation instructions). Request permanent audio focus when you plan to play audio for the foreseeable future (for example, when playing music).

The following snippet requests permanent audio focus on the music audio stream. You should request the audio focus immediately before you begin playback, such as when the user presses play or the background music for the next game level begins.

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                                 // Use the music stream.
                                 AudioManager.STREAM_MUSIC,
                                 // Request permanent focus.
                                 AudioManager.AUDIOFOCUS_GAIN);
   
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
    // Start playback.
}

Once you’ve finished playback be sure to call abandonAudioFocus(). This notifies the system that you no longer require focus and unregisters the associated AudioManager.OnAudioFocusChangeListener. In the case of abandoning transient focus, this allows any interupted app to continue playback.

// Abandon audio focus when playback complete    
am.abandonAudioFocus(afChangeListener);

When requesting transient audio focus you have an additional option: whether or not you want to enable “ducking.” Normally, when a well-behaved audio app loses audio focus it immediately silences its playback. By requesting a transient audio focus that allows ducking you tell other audio apps that it’s acceptable for them to keep playing, provided they lower their volume until the focus returns to them.

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                             // Use the music stream.
                             AudioManager.STREAM_MUSIC,
                             // Request permanent focus.
                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
   
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback.
}

Ducking is particularly suitable for apps that use the audio stream intermittently, such as for audible driving directions.

Whenever another app requests audio focus as described above, its choice between permanent and transient (with or without support for ducking) audio focus is received by the listener you registered when requesting focus.

Handle the Loss of Audio Focus


If your app can request audio focus, it follows that it will in turn lose that focus when another app requests it. How your app responds to a loss of audio focus depends on the manner of that loss.

The onAudioFocusChange() callback method of they audio focus change listener you registered when requesting audio focus receives a parameter that describes the focus change event. Specifically, the possible focus loss events mirror the focus request types from the previous section—permanent loss, transient loss, and transient with ducking permitted.

Generally speaking, a transient (temporary) loss of audio focus should result in your app silencing it’s audio stream, but otherwise maintaining the same state. You should continue to monitor changes in audio focus and be prepared to resume playback where it was paused once you’ve regained the focus.

If the audio focus loss is permanent, it’s assumed that another application is now being used to listen to audio and your app should effectively end itself. In practical terms, that means stopping playback, removing media button listeners—allowing the new audio player to exclusively handle those events—and abandoning your audio focus. At that point, you would expect a user action (pressing play in your app) to be required before you resume playing audio.

In the following code snippet, we pause the playback or our media player object if the audio loss is transient and resume it when we have regained the focus. If the loss is permanent, it unregisters our media button event receiver and stops monitoring audio focus changes.

 

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
            // Pause playback
        } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Resume playback 
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
            am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
            am.abandonAudioFocus(afChangeListener);
            // Stop playback
        }
    }
};

In the case of a transient loss of audio focus where ducking is permitted, rather than pausing playback, you can “duck” instead.

Duck!


Ducking is the process of lowering your audio stream output volume to make transient audio from another app easier to hear without totally disrupting the audio from your own application.

In the following code snippet lowers the volume on our media player object when we temporarily lose focus, then returns it to its previous level when we regain focus.

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
            // Lower the volume
        } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Raise it back to normal
        }
    }
};

A loss of audio focus is the most important broadcast to react to, but not the only one. The system broadcasts a number of intents to alert you to changes in user’s audio experience. The next lesson demonstrates how to monitor them to improve the user’s overall experience.

Steps for Content Provider

29th July 2013,

This involves number of simple steps to create your own content provider.

  • First of all you need to create a Content Provider class that extends the ContentProviderbaseclass.
  • Second, you need to define your content provider URI address which will be used to access the content.
  • Next you will need to create your own database to keep the content. Usually, Android uses SQLite database and framework needs to override onCreate() method which will use SQLite Open Helper method to create or open the provider’s databse. When your application is launched, theonCreate() handler of each of its Content Providers is called on the main application thread.
  • Next you will have to implement Content Provider queries to perform different database specific operations.
  • Finally register your Content Provider in your acitivity file using <provider> tag.

Here is the list of methods which you need to override in Content Provider class to have your Content Provider working:

  • onCreate() This method is called when the provider is started.
  • query() This method receives a request from a client. The result is returned as a Cursor object.
  • insert()This method inserts a new record into the content provider.
  • delete() This method deletes an existing record from the content provider.
  • update() This method updates an existing record from the content provider.
  • getType() This method returns the MIME type of the data at the given URI.

Controlling Your App’s Volume and Playback

A good user experience is a predictable one. If your app plays media it’s important that your users can control the volume of your app using the hardware or software volume controls of their device, bluetooth headset, or headphones.

Similarly, where appropriate and available, the play, stop, pause, skip, and previous media playback keys should perform their respective actions on the audio stream used by your app.

Identify Which Audio Stream to Use


The first step to creating a predictable audio experience is understanding which audio stream your app will use.

Android maintains a separate audio stream for playing music, alarms, notifications, the incoming call ringer, system sounds, in-call volume, and DTMF tones. This is done primarily to allow users to control the volume of each stream independently.

Most of these streams are restricted to system events, so unless your app is a replacement alarm clock, you’ll almost certainly be playing your audio using the STREAM_MUSIC stream.

Use Hardware Volume Keys to Control Your App’s Audio Volume


By default, pressing the volume controls modify the volume of the active audio stream. If your app isn’t currently playing anything, hitting the volume keys adjusts the ringer volume.

 

If you’ve got a game or music app, then chances are good that when the user hits the volume keys they want to control the volume of the game or music, even if they’re currently between songs or there’s no music in the current game location.

You may be tempted to try and listen for volume key presses and modify the volume of your audio stream that way. Resist the urge. Android provides the handy setVolumeControlStream() method to direct volume key presses to the audio stream you specify.

 

Having identified the audio stream your application will be using, you should set it as the volume stream target. You should make this call early in your app’s lifecycle—because you only need to call it once during the activity lifecycle, you should typically call it within the onCreate() method (of the Activity orFragment that controls your media). This ensures that whenever your app is visible, the volume controls function as the user expects.

 

setVolumeControlStream(AudioManager.STREAM_MUSIC);

From this point onwards, pressing the volume keys on the device affect the audio stream you specify (in this case “music”) whenever the target activity or fragment is visible.

Use Hardware Playback Control Keys to Control Your App’s Audio Playback


Media playback buttons such as play, pause, stop, skip, and previous are available on some handsets and many connected or wireless headsets. Whenever a user presses one of these hardware keys, the system broadcasts an intent with the ACTION_MEDIA_BUTTON action.

To respond to media button clicks, you need to register a BroadcastReceiver in your manifest that listens for this action broadcast as shown below.

<receiver android:name=".RemoteControlReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

The receiver implementation itself needs to extract which key was pressed to cause the broadcast. TheIntent includes this under the EXTRA_KEY_EVENT key, while the KeyEvent class includes a listKEYCODE_MEDIA_* static constants that represents each of the possible media buttons, such asKEYCODE_MEDIA_PLAY_PAUSE and KEYCODE_MEDIA_NEXT.

The following snippet shows how to extract the media button pressed and affects the media playback accordingly.

public class RemoteControlReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
            KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
                // Handle key press.
            }
        }
    }
}

Because multiple applications might want to listen for media button presses, you must also programmatically control when your app should receive media button press events.

The following code can be used within your app to register and de-register your media button event receiver using the AudioManager. When registered, your broadcast receiver is the exclusive receiver of all media button broadcasts.

 

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...

// Start listening for button presses
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
...

// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);

Typically, apps should unregister most of their receivers whenever they become inactive or invisible (such as during the onStop() callback). However, it’s not that simple for media playback apps—in fact, responding to media playback buttons is most important when your application isn’t visible and therefore can’t be controlled by the on-screen UI.

Detail of content provider

26th July 2013,

To query a content provider, you specify the query string in the form of a URI which has following format:

<prefix>://<authority>/<data_type>/<id>

Here is the detaial of various parts of the URI:

1. prefix- This is always set to content://

2. authority- This specifies the name of the content provider, for example contactsbrowser etc. For third-party content providers, this could be the fully qualified name, such ascom.tutorialspoint.statusprovider

3. data_type- This indicates the type of data that this particular provider provides. For example, if you are getting all the contacts from the Contacts content provider, then the data path would be people and URI would look like this content://contacts/people

4. id- This specifies the specific record requested. For example, if you are looking for contact number 5 in the Contacts content provider then URI would look like thiscontent://contacts/people/5.

Receiving Files from Another Device

Android Beam file transfer copies files to a special directory on the receiving device. It also scans the copied files using the Android Media Scanner and adds entries for media files to the MediaStore provider. This lesson shows you how to respond when the file copy is complete, and how to locate the copied files on the receiving device.

Respond to a Request to Display Data


When Android Beam file transfer finishes copying files to the receiving device, it posts a notification containing an Intentwith the action ACTION_VIEW, the MIME type of the first file that was transferred, and a URI that points to the first file. When the user clicks the notification, this intent is sent out to the system. To have your app respond to this intent, add an <intent-filter> element for the <activity> element of the Activity that should respond. In the <intent-filter> element, add the following child elements:

<action android:name="android.intent.action.VIEW" />
Matches the ACTION_VIEW intent sent from the notification.
<category android:name="android.intent.category.CATEGORY_DEFAULT" />
Matches an Intent that doesn’t have an explicit category.
<data android:mimeType="mime-type" />
Matches a MIME type. Specify only those MIME types that your app can handle.

For example, the following snippet shows you how to add an intent filter that triggers the activitycom.example.android.nfctransfer.ViewActivity:

    <activity
        android:name="com.example.android.nfctransfer.ViewActivity"
        android:label="Android Beam Viewer" >
        ...
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            ...
        </intent-filter>
    </activity>

Note: Android Beam file transfer is not the only source of an ACTION_VIEW intent. Other apps on the receiving device can also send an Intent with this action. Handling this situation is discussed in the section Get the directory from a content URI.

Request File Permissions


To read files that Android Beam file transfer copies to the device, request the permissionREAD_EXTERNAL_STORAGE. For example:

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

If you want to copy transferred files to your app’s own storage area, request the permissionWRITE_EXTERNAL_STORAGE instead. WRITE_EXTERNAL_STORAGE includes READ_EXTERNAL_STORAGE.

Note: As of Android 4.2.2 (API level 17), the permission READ_EXTERNAL_STORAGE is only enforced if the user chooses to do so. Future versions of the platform may require this permission in all cases. To ensure forward compatibility, request the permission now, before it becomes required.

Since your app has control over its internal storage area, you don’t need to request write permission to copy a transferred file to your internal storage area.

Get the Directory for Copied Files


Android Beam file transfer copies all the files in a single transfer to one directory on the receiving device. The URI in the content Intent sent by the Android Beam file transfer notification points to the first transferred file. However, your app may also receive an ACTION_VIEW intent from a source other than Android Beam file transfer. To determine how you should handle the incoming Intent, you need to examine its scheme and authority.

To get the scheme for the URI, call Uri.getScheme(). The following code snippet shows you how to determine the scheme and handle the URI accordingly:

public class MainActivity extends Activity {
    ...
    // A File object containing the path to the transferred files
    private File mParentPath;
    // Incoming Intent
    private Intent mIntent;
    ...
    /*
     * Called from onNewIntent() for a SINGLE_TOP Activity
     * or onCreate() for a new Activity. For onNewIntent(),
     * remember to call setIntent() to store the most
     * current Intent
     *
     */
    private void handleViewIntent() {
        ...
        // Get the Intent action
        mIntent = getIntent();
        String action = mIntent.getAction();
        /*
         * For ACTION_VIEW, the Activity is being asked to display data.
         * Get the URI.
         */
        if (TextUtils.equals(action, Intent.ACTION_VIEW)) {
            // Get the URI from the Intent
            Uri beamUri = mIntent.getData();
            /*
             * Test for the type of URI, by getting its scheme value
             */
            if (TextUtils.equals(beamUri.getScheme(), "file")) {
                mParentPath = handleFileUri(beamUri);
            } else if (TextUtils.equals(
                    beamUri.getScheme(), "content")) {
                mParentPath = handleContentUri(beamUri);
            }
        }
        ...
    }
    ...
}

Get the directory from a file URI

If the incoming Intent contains a file URI, the URI contains the absolute file name of a file, including the full directory path and file name. For Android Beam file transfer, the directory path points to the location of the other transferred files, if any. To get the directory path, get the path part of the URI, which contains all of the URI except the file: prefix. Create a File from the path part, then get the parent path of the File:

    ...
    public String handleFileUri(Uri beamUri) {
        // Get the path part of the URI
        String fileName = beamUri.getPath();
        // Create a File object for this filename
        File copiedFile = new File(fileName);
        // Get a string containing the file's parent directory
        return copiedFile.getParent();
    }
    ...

Get the directory from a content URI

If the incoming Intent contains a content URI, the URI may point to a directory and file name stored in theMediaStore content provider. You can detect a content URI for MediaStore by testing the URI’s authority value. A content URI for MediaStore may come from Android Beam file transfer or from another app, but in both cases you can retrieve a directory and file name for the content URI.

You can also receive an incoming ACTION_VIEW intent containing a content URI for a content provider other than MediaStore. In this case, the content URI doesn’t contain the MediaStore authority value, and the content URI usually doesn’t point to a directory.

Note: For Android Beam file transfer, you receive a content URI in the ACTION_VIEW intent if the first incoming file has a MIME type of “audio/*”, “image/*”, or “video/*”, indicating that the file is media- related. Android Beam file transfer indexes the media files it transfers by running Media Scanner on the directory where it stores transferred files. Media Scanner writes its results to the MediaStore content provider, then it passes a content URI for the first file back to Android Beam file transfer. This content URI is the one you receive in the notification Intent. To get the directory of the first file, you retrieve it from MediaStoreusing the content URI.

Determine the content provider

To determine if you can retrieve a file directory from the content URI, determine the the content provider associated with the URI by calling Uri.getAuthority() to get the URI’s authority. The result has two possible values:

MediaStore.AUTHORITY
The URI is for a file or files tracked by MediaStore. Retrieve the full file name from MediaStore, and get directory from the file name.
Any other authority value
A content URI from another content provider. Display the data associated with the content URI, but don’t get the file directory.

To get the directory for a MediaStore content URI, run a query that specifies the incoming content URI for the Uri argument and the column MediaColumns.DATA for the projection. The returned Cursor contains the full path and name for the file represented by the URI. This path also contains all the other files that Android Beam file transfer just copied to the device.

The following snippet shows you how to test the authority of the content URI and retrieve the the path and file name for the transferred file:

    ...
    public String handleContentUri(Uri beamUri) {
        // Position of the filename in the query Cursor
        int filenameIndex;
        // File object for the filename
        File copiedFile;
        // The filename stored in MediaStore
        String fileName;
        // Test the authority of the URI
        if (!TextUtils.equals(beamUri.getAuthority(), MediaStore.AUTHORITY)) {
            /*
             * Handle content URIs for other content providers
             */
        // For a MediaStore content URI
        } else {
            // Get the column that contains the file name
            String[] projection = { MediaStore.MediaColumns.DATA };
            Cursor pathCursor =
                    getContentResolver().query(beamUri, projection,
                    null, null, null);
            // Check for a valid cursor
            if (pathCursor != null &&
                    pathCursor.moveToFirst()) {
                // Get the column index in the Cursor
                filenameIndex = pathCursor.getColumnIndex(
                        MediaStore.MediaColumns.DATA);
                // Get the full file name including path
                fileName = pathCursor.getString(filenameIndex);
                // Create a File object for the filename
                copiedFile = new File(fileName);
                // Return the parent directory of the file
                return new File(copiedFile.getParent());
             } else {
                // The query didn't work; return null
                return null;
             }
        }
    }

Content Provider in Android

25th July 2013,

A content provider component supplies data from one application to others on request. Such requests are handled by the methods of the ContentResolver class. A content provider can use different ways to store its data and the data can be stored in a database, in files, or even over a network.

Each Android applications runs in its own process with its own permissions which keeps an application data hidden from another application. But sometimes it is required to share data across applications. This is where content providers become very useful.

Content providers let you centralize content in one place and have many different applications access it as needed. A content provider behaves very much like a database where you can query it, edit its content, as well as add or delete content usingg insert(), update(), delete(), and query() methods. In most cases this data is stored in an SQlite database.

A content provider is implemented as a subclass of ContentProvider class and must implement a standard set of APIs that enable other applications to perform transactions.

public class MyContentProvider extends  ContentProvider {

}

Check Current Running App

24th July 2013,

AndroidMainifest.xml

<?xml version="1.0" encoding="utf-8"?>
    package="com.example.checkcurrentrunningapplication"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="10"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.checkcurrentrunningapplication.Main"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <receiver android:name=".StartupReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="StartupReceiver_Manual_Start" />
            </intent-filter>
        </receiver>
        
        <receiver android:name = ".CheckRunningApplicationReceiver"/>
        
    </application>
    <uses-permission android:name="android.permission.GET_TASKS" />
</manifest>

File : src/Main.java

Inside This class Start Broadcast reciever to check current running activity/task/application.

package com.example.checkcurrentrunningapplication;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
public class Main extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         
        // Start broadcast receiver may be StartupReceiver not started on BOOT_COMPLETED
        // Check AndroidManifest.xml file
        initialize();
    }
    private void initialize() {
        
        // Start receiver with the name StartupReceiver_Manual_Start
        // Check AndroidManifest.xml file
        getBaseContext().getApplicationContext().sendBroadcast(
                new Intent("StartupReceiver_Manual_Start"));
    }
}

File : src/StartupReceiver.java

This receiver will on phone boot time (see AndroidMainifest.xml). Creating alarm that will call broadcast receiver CheckRunningApplicationReceiver.class after each 5 seconds.

package com.example.checkcurrentrunningapplication;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.util.Log;
public class StartupReceiver extends BroadcastReceiver {
    static final String TAG = "SR";
    
    final int startupID = 1111111;
    
    @Override
    public void onReceive(Context context, Intent intent) {
        
        // Create AlarmManager from System Services
        final AlarmManager alarmManager = (AlarmManager) context
                    .getSystemService(Context.ALARM_SERVICE);
        try{
                // Create pending intent for CheckRunningApplicationReceiver.class
                // it will call after each 5 seconds
                
                Intent i7 = new Intent(context, CheckRunningApplicationReceiver.class);
                PendingIntent ServiceManagementIntent = PendingIntent.getBroadcast(context,
                        startupID, i7, 0);
                alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,
                        SystemClock.elapsedRealtime(),
                        5000, ServiceManagementIntent);
                
                
            } catch (Exception e) {
                Log.i(TAG, "Exception : "+e);
            }
            
        }
    
}

File : src/CheckRunningApplicationReceiver.java

This broadcast receiver will call after each 5 seconds and check CALL/SMS/THIS example screen is open or not. if CALL/SMS/THIS example screen open then show alert message on screen.

package com.example.checkcurrentrunningapplication;
import java.util.List;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class CheckRunningApplicationReceiver extends BroadcastReceiver {
    public final String TAG = "CRAR"; // CheckRunningApplicationReceiver
    @Override
    public void onReceive(Context aContext, Intent anIntent) {
        
        try {
            
            // Using ACTIVITY_SERVICE with getSystemService(String)
            // to retrieve a ActivityManager for interacting with the global system state.
            
            ActivityManager am = (ActivityManager) aContext
                    .getSystemService(Context.ACTIVITY_SERVICE);
            
            // Return a list of the tasks that are currently running,
            // with the most recent being first and older ones after in order.
            // Taken 1 inside getRunningTasks method means want to take only
            // top activity from stack and forgot the olders.
            
            List<ActivityManager.RunningTaskInfo> alltasks = am
                    .getRunningTasks(1);
            //
            for (ActivityManager.RunningTaskInfo aTask : alltasks) {
                
                // Used to check for CALL screen 
                
                if (aTask.topActivity.getClassName().equals("com.android.phone.InCallScreen")
                    || aTask.topActivity.getClassName().equals("com.android.contacts.DialtactsActivity"))
                {
                    // When user on call screen show a alert message
                    Toast.makeText(aContext, "Phone Call Screen.", Toast.LENGTH_LONG).show();  
                }
                
                // Used to check for SMS screen
                
                if (aTask.topActivity.getClassName().equals("com.android.mms.ui.ConversationList")
                        || aTask.topActivity.getClassName().equals("com.android.mms.ui.ComposeMessageActivity"))
                {
                    // When user on Send SMS screen show a alert message
                    Toast.makeText(aContext, "Send SMS Screen.", Toast.LENGTH_LONG).show();
                }
                
                
                // Used to check for CURRENT example main screen
                
                String packageName = "com.example.checkcurrentrunningapplication";
                
                if (aTask.topActivity.getClassName().equals(
                        packageName + ".Main"))
                {
                   // When opens this example screen then show a alert message
                   Toast.makeText(aContext, "Check Current Running Application Example Screen.",
                                   Toast.LENGTH_LONG).show();  
                }
                
                
                // These are showing current running activity in logcat with
                // the use of different methods
                
                Log.i(TAG, "===============================");
                
                    Log.i(TAG, "aTask.baseActivity: "
                                + aTask.baseActivity.flattenToShortString());
                    
                    Log.i(TAG, "aTask.baseActivity: "
                                + aTask.baseActivity.getClassName());
                    
                    Log.i(TAG, "aTask.topActivity: "
                                + aTask.topActivity.flattenToShortString());
                    
                    Log.i(TAG, "aTask.topActivity: "
                                + aTask.topActivity.getClassName());
                
                Log.i(TAG, "===============================");
                
                
            }
        } catch (Throwable t) {
            Log.i(TAG, "Throwable caught: "
                        + t.getMessage(), t);
        }
        
    }
}

File : 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=".Main" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Starting broadcast reciever to check current running tasks." />
</RelativeLayout>

Logcat Output Screenshot :

logcat_output_for_current_open_activity_6

Sharing Files with NFC

Android allows you to transfer large files between devices using the Android Beam file transfer feature. This feature has a simple API and allows users to start the transfer process by simply touching devices. In response, Android Beam file transfer automatically copies files from one device to the other and notifies the user when it’s finished.

While the Android Beam file transfer API handles large amounts of data, the Android Beam NDEF transfer API introduced in Android 4.0 (API level 14) handles small amounts of data such as URIs or other small messages. In addition, Android Beam is only one of the features available in the Android NFC framework, which allows you to read NDEF messages from NFC tags. To learn more about Android Beam, see the topic Beaming NDEF Messages to Other Devices. To learn more about the NFC framework, see the Near Field Communication API guide.

Sending Files to Another Device

PREVIOUSNEXT

THIS LESSON TEACHES YOU TO

  1. Declare Features in the Manifest
  2. Test for Android Beam File Transfer Support
  3. Create a Callback Method That Provides Files
  4. Specify the Files to Send

YOU SHOULD ALSO READ

  • Storage Options

This lesson shows you how to design your app to send large files to another device using Android Beam file transfer. To send files, you request permission to use NFC and external storage, test to ensure your device supports NFC, and provide URIs to Android Beam file transfer.

The Android Beam file transfer feature has the following requirements:

  1. Android Beam file transfer for large files is only available in Android 4.1 (API level 16) and higher.
  2. Files you want to transfer must reside in external storage. To learn more about using external storage, read Using the External Storage.
  3. Each file you want to transfer must be world-readable. You can set this permission by calling the methodFile.setReadable(true,false).
  4. You must provide a file URI for the files you want to transfer. Android Beam file transfer is unable to handle content URIs generated by FileProvider.getUriForFile.

Declare Features in the Manifest


First, edit your app manifest to declare the permissions and features your app needs.

Request Permissions

To allow your app to use Android Beam file transfer to send files from external storage using NFC, you must request the following permissions in your app manifest:

NFC
Allows your app to send data over NFC. To specify this permission, add the following element as a child of the <manifest> element:

    <uses-permission android:name="android.permission.NFC" />
READ_EXTERNAL_STORAGE
Allows your app to read from external storage. To specify this permission, add the following element as a child of the <manifest> element:

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

Note: As of Android 4.2.2 (API level 17), this permission is not enforced. Future versions of the platform may require it for apps that want to read from external storage. To ensure forward compatibility, request the permission now, before it becomes required.

Specify the NFC feature

Specify that your app uses NFC, by adding a <uses-feature> element as a child of the <manifest>element. Set the android:required attribute to true to indicate that your app won’t function unless NFC is present.

The following snippet shows you how to specify the <uses-feature> element:

<uses-feature
    android:name="android.hardware.nfc"
    android:required="true" />

Note that if your app only uses NFC as an option, but still functions if NFC isn’t present, you should setandroid:required to false, and test for NFC in code.

Specify Android Beam file transfer

Since Android Beam file transfer is only available in Android 4.1 (API level 16) and later, if your app depends on Android Beam file transfer for a key part of its functionality you must specify the <uses-sdk> element with the android:minSdkVersion="16" attribute. Otherwise, you can set android:minSdkVersion to another value as necessary, and test for the platform version in code, as described in the following section.

Test for Android Beam File Transfer Support


To specify in your app manifest that NFC is optional, you use the following element:

<uses-feature android:name="android.hardware.nfc" android:required="false" />

If you set the attribute android:required="false", you must test for NFC support and Android Beam file transfer support in code.

To test for Android Beam file transfer support in code, start by testing that the device supports NFC by callingPackageManager.hasSystemFeature() with the argument FEATURE_NFC. Next, check that the Android version supports Android Beam file transfer by testing the value of SDK_INT. If Android Beam file transfer is supported, get an instance of the NFC controller, which allows you to communicate with the NFC hardware. For example:

public class MainActivity extends Activity {
    ...
    NfcAdapter mNfcAdapter;
    // Flag to indicate that Android Beam is available
    boolean mAndroidBeamAvailable  = false;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        // NFC isn't available on the device
        if (!PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) {
            /*
             * Disable NFC features here.
             * For example, disable menu items or buttons that activate
             * NFC-related features
             */
            ...
        // Android Beam file transfer isn't supported
        } else if (Build.VERSION.SDK_INT <
                Build.VERSION_CODES.JELLY_BEAN_MR1) {
            // If Android Beam isn't available, don't continue.
            mAndroidBeamAvailable = false;
            /*
             * Disable Android Beam file transfer features here.
             */
            ...
        // Android Beam file transfer is available, continue
        } else {
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        ...
        }
    }
    ...
}

Create a Callback Method that Provides Files


Once you’ve verified that the device supports Android Beam file transfer, add a callback method that the system invokes when Android Beam file transfer detects that the user wants to send files to another NFC-enabled device. In this callback method, return an array of Uri objects. Android Beam file transfer copies the files represented by these URIs to the receiving device.

To add the callback method, implement the NfcAdapter.CreateBeamUrisCallback interface and its method createBeamUris(). The following snippet shows you how to do this:

public class MainActivity extends Activity {
    ...
    // List of URIs to provide to Android Beam
    private Uri[] mFileUris = new Uri[10];
    ...
    /**
     * Callback that Android Beam file transfer calls to get
     * files to share
     */
    private class FileUriCallback implements
            NfcAdapter.CreateBeamUrisCallback {
        public FileUriCallback() {
        }
        /**
         * Create content URIs as needed to share with another device
         */
        @Override
        public Uri[] createBeamUris(NfcEvent event) {
            return mFileUris;
        }
    }
    ...
}

Once you’ve implemented the interface, provide the callback to Android Beam file transfer by callingsetBeamPushUrisCallback(). The following snippet shows you how to do this:

public class MainActivity extends Activity {
    ...
    // Instance that returns available files from this app
    private FileUriCallback mFileUriCallback;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        // Android Beam file transfer is available, continue
        ...
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        /*
         * Instantiate a new FileUriCallback to handle requests for
         * URIs
         */
        mFileUriCallback = new FileUriCallback();
        // Set the dynamic callback for URI requests.
        mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this);
        ...
    }
    ...
}

Note: You can also provide the array of Uri objects directly to the NFC framework through your app’sNfcAdapter instance. Choose this approach if you can define the URIs to transfer before the NFC touch event occurs. To learn more about this approach, see NfcAdapter.setBeamPushUris().

Specify the Files to Send


To transfer one or more files to another NFC-enabled device, get a file URI (a URI with a file scheme) for each file and then add the URI to an array of Uri objects. To transfer a file, you must also have permanent read access for the file. For example, the following snippet shows you how to get a file URI from a file name and then add the URI to the array:

        /*
         * Create a list of URIs, get a File,
         * and set its permissions
         */
        private Uri[] mFileUris = new Uri[10];
        String transferFile = "transferimage.jpg";
        File extDir = getExternalFilesDir(null);
        File requestFile = new File(extDir, transferFile);
        requestFile.setReadable(true, false);
        // Get a URI for the File and add it to the list of URIs
        fileUri = Uri.fromFile(requestFile);
        if (fileUri != null) {
            mFileUris[0] = fileUri;
        } else {
            Log.e("My Activity", "No File URI available for file.");
        }

Icomming call BroadCast Receiver

23rd July 2013,

1. Declare receiver in AndroidManifest

    <receiver android:name=”.IncomingCall“>
<intent-filter>
<action android:name=”android.intent.action.PHONE_STATE” />
</intent-filter>
</receiver>

  2. Give read phone state permission in AndroidManifest

         <uses-permission android:name=”android.permission.READ_PHONE_STATE”></uses-permission>

Complete code for AndroidManifest.xml File :

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
package=”com.androidexample.broadcastreceiver”
android:versionCode=”1″
android:versionName=”1.0″ >

<application
android:allowBackup=”true”
android:icon=”@drawable/ic_launcher”
android:label=”@string/app_name”
android:theme=”@style/AppTheme” >
<activity
android:name=”com.androidexample.broadcastreceiver.BroadcastPhoneStates”
android:label=”@string/app_name” >
<intent-filter>
<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>

<receiver android:name=”.IncomingCall”>
<intent-filter>
<action android:name=”android.intent.action.PHONE_STATE” />
</intent-filter>
</receiver>

</application>
<uses-sdk
android:minSdkVersion=”8″
android:targetSdkVersion=”17″ />

  <uses-permission android:name=”android.permission.READ_PHONE_STATE”></uses-permission>

</manifest>

—————————————————————————————————————————————

IncomingCall.java file details :

I have made broadcast event reciever in this file

 1. Created class IncomingCall with extends BroadcastReceiver class

        public class IncomingCall extends BroadcastReceiver

2.  Create method receiver()

               public void onReceive(Context context, Intent intent)

        3. Create listener to read phone state

               // TELEPHONY MANAGER class object to register one listner
TelephonyManager tmgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);

//Create Listner
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();

// Register listener for LISTEN_CALL_STATE
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);

 4.  Create phone state listner class

When new call come the onCallStateChanged method called

        private class MyPhoneStateListener extends PhoneStateListener {

public void onCallStateChanged(int state, String incomingNumber) {

// Log.d(“MyPhoneListener”,state+”   incoming no:”+incomingNumber);
  // state = 1 means when phone is ringing
if (state == 1) {

String msg = ” New Phone Call Event. Incomming Number : “+incomingNumber;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(pcontext, msg, duration);
toast.show();

}
}
}

Complete code for  IncomingCall.java file :

public class IncomingCall extends BroadcastReceiver {

public void onReceive(Context context, Intent intent) {

try {
// TELEPHONY MANAGER class object to register one listner
TelephonyManager tmgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);

//Create Listner
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();

// Register listener for LISTEN_CALL_STATE
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);

} catch (Exception e) {
Log.e(“Phone Receive Error”, ” ” + e);
}

}

private class MyPhoneStateListener extends PhoneStateListener {

public void onCallStateChanged(int state, String incomingNumber) {

Log.d(“MyPhoneListener”,state+”   incoming no:”+incomingNumber);

if (state == 1) {

String msg = “New Phone Call Event. Incomming Number : “+incomingNumber;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(pcontext, msg, duration);
toast.show();

}
}
}
}