Receiver-side Implementation

 

Portions of this page are reproduced from work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

On the object receiver side, you should handle the DragEvent. If the drag starts on the sender side applidation, the system sends a DragEvent to the drag listener on the receiver side application.

 

Action Types of DragEvent

DragEvent object contains an action type that tells the listener what is happening in the drag and drop process. To get the action type, you should call the getAction().

There are six possible values defined by constants in the DragEvent class as follows:

 

Value

Description

ACTION_DRAG_STARTED

 

• Signal indicating the start of a drag-and-drop operation.

• The system sends a drag event with this action type when the user starts a drag gesture.

 

ACTION_DRAG_ENTERED

 

• Signal indicating that the drag shadow has entered the bounding box of the View.

• The system sends a drag event with this action type when the touch point has entered the bounding box of the View.

 

ACTION_DRAG_LOCATION

 

• Signal indicating that the drag shadow is still within the bounding box of the View.

• The system sends a drag event with this action type after sending ACTION_DRAG_ENTERED and before sending ACTION_DRAG_EXITED, every time the touch point moves.

 

ACTION_DRAG_EXITED

 

• Signal indicating that the drag shadow is no longer within the bounding box of the listener's View.

• The system sends a drag event with this action type after sending the ACTION_DRAG_EXITED when the user has moved the drag shadow outside the bounding box of the View.

 

ACTION_DROP

 

• Signal indicating the drop operation to the target View area.

• The system sends a drag event with this action type to the view when the user releases the drag shadow and the drag point is within the bounding box of the View.

 

ACTION_DRAG_ENDED

 

• Signal indicating the drag-and-drop operation has concluded.

• The system sends a drag event with this action type immediately after the user releases the drag shadow.

 

 

ACTION_DRAG_STARTED
In response to an drag event with this action type, you should do the following:
1. Check the mimeType to see if you can accept the data being dragged. You can get the mimeType form ClipDescription by calling getClipDescription().
2. Return true only if the data can be accepted. This tells the system to continue to send drag events continuously:
 
ACTION_DRAG_ENTERED
In response to an event with this action type, you should do the following:
1. You can get the focus for the View by calling requestFocus().
2. You can change the View appearance to indicate that it is about to receive a drop.
 
ACTION_DRAG_LOCATION
In response to an event with this action type, you should do the following:
1. You can get the valid data for getX() and getY(), corresponding to the location of the touch point. This data can be used to determine the exact position where the user is going to drop the drag shadow.
 
ACTION_DRAG_EXITED
In response to an event with this action type, you should do the following:
1. You can reset the appearance changes by ACTION_DRAG_ENTERED or ACTION_DRAG_LOCATED.
 
ACTION_DROP
In response to an event with this action type, you should do the following:
1. Get the ClipData object that was passed by startDrag(). You can get the ClipData by calling getClipData().
2. Return true to indicate that the drop was processed successfully, or return false if it was not. This is used for the action type ACTION_DRAG_ENDED.

 

ACTION_DRAG_ENDED
In response to an event with this action type, you should do the following:
1. Reset the View to its default appearance if its appearance was changed during the drag-and-drop operation.
2. Check the result by calling getResult(). It returns true only if ACTION_DROP returns true. In all other cases, it returns false.
3. Return true to indicate that the drag and drop has been completed successfully.

 

Two approaches for handling the DragEvent

The target View to drop can receive the DragEvent from the system in two ways.
1. Setting the OnDragListener to the View
2. Overriding the onDragEvent() of the View

 

During the drag operation, the system calls the listener (OnDragListener) or the callback method (onDragEvent()) and passes a DragEvent object to them.
If you use both OnDragListener and onDragEvent(), the system first calls the listener. If the listener returns true, the system does not the call onDragEvent().

 

Refer to the following examples:

 

Example: OnDragListener

public class ReceiverActivity extends Activity {
public void onCreate( Bundle savedInstanceState) {
View v = findViewById(R.id.view_to_drop);
v.setOnDragListener(draglistener);
}
View.OnDragListener draglistener= new View.OnDragListener( ) {
// This is the method the system calls when it dispatches a 
// drag event to the listener @Override
public boolean onDrag(View v, DragEventevent) {
// if this returns true, note that the event will not be passed 
// into onDragEvent. It is because that onDragListener is 
// prior to onDragEvent(.)
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// True should be returned here, if this view want to 
// receive drag events later on.
// isSupportedMimeType() returns true if this View can 
// accept the dragged data
return isSupportedMimeType(event.getClipDescription());
case DragEvent.ACTION_DRAG_ENTERED:
v.requestFocus();
return true;
case DragEvent.ACTION_DROP:
return onDrop(event);
// Do something with the dropped Uri data. 
// Return true only if the data is handled here
}
return false;
}
}
...
}

 

Example: onDragEvent()

public class ReceiverActivity extends Activity {
public void onCreate( Bundle savedInstanceState) {
CustomViewv = (CustomView) findViewById(R.id.view_to_drop);
}
class CustomViewextends View {
@Override
public booleanon DragEvent(DragEventevent) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// True should be returned here, if this view want to receive drag events later on.
// isSupportedMimeType() returns ture if this View can accept the dragged data
return isSupportedMimeType(event.getClipDescription());
case DragEvent.ACTION_DRAG_ENTERED:
this.requestFocus();
return true;
case DragEvent.ACTION_DROP:
return onDrop(event);
// Do something with the dropped data.
// Return true only if the data is handled here
}
return false;
}
}
...
}

 

Responding to the Drop

Getting the ClipData

In response to the drop, you should get the ClipData which was created in the Sender App. It is included in the DragEvent and you can get it using the getClipData() method.
ClipData.Item can then be obtained from the ClipData.
ClipData clip = event.getClipData();
ClipData.Item item = clip.getItemAt(0);
 
The data should be processed appropriately depending on its mimeType. This document explains two cases for the plain text ClipData and URI ClipData.

Processing Text ClipData

1. Get the mimeType of the ClipDescription.
2. Check that the mimeType of the ClipDescription is valid for the plain text.
If you created the ClipData using newPlainText (), it is set to the same value of the ClipDescription constant.MIMETYPE_TEXT_PLAIN.
3. Get the plain text data from ClipData.Item. You can get the dragged text data using the item.getText() because the ClipData.Item includes the text data in case the ClipData is created using newPlainText().
String mimeType = clip.getDescription().getMimeType(0);
if (mimeType.equals(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
CharSequence plainText = item.getText();
//Do something that you want to do with dragged text clip data
}

 

Processing the URI ClipData

1. Get the URI from ClipData.Item.

private Uri getUri(ClipDataclip) {
if (clip == null) {
return null;
}
ClipData.Item item;
Uri uri;
for (inti= 0 ; i< clip.getItemCount(); i++) {
item = clip.getItemAt(i);
uri= item.getUri();
if(uri!= null) {
return uri;
}
}
return null;
}

 

2. Get the valid mimeType as follows:
- First, use the mimeType of the ClipDescription.
- Second, there is no valid mimeType in the ClipDescription; create the mimeType using the URI.
private boolean hasValidMimeType(ClipData clip) {
String mimeType= getUriMimeType(this,clip);
//check that the mimeType is vaild
if(isValidUriMimeType(mimeType)) {
return true;
}
return false;
}
public static String getUriMimeType(Context context, ClipDataclip) { // get uri
Uri uri= getUri(clip);
if(uri== null) {
return null;
}
// retrieve mimeTypeof uriinside ClipDescription
String uriMimeType= getUriMimeType(clip.getDescription());
// if there's no mime type in ClipDescription, get it from uri
if(uriMimeType== null) {
uriMimeType= getMimeTypeFromUri(context, uri);
}
return uriMimeType;
}
public static String getUriMimeType(ClipDescriptiondesc) {
if (desc== null) {
return null;
}
String uriMimeType= null;
String mimeType;
for (inti= 0; i< desc.getMimeTypeCount(); i++) {
mimeType= desc.getMimeType(i);
if (mimeType.equals(ClipDescription.MIMETYPE_TEXT_HTML) ||
mimeType.equals(ClipDescription.MIMETYPE_TEXT_INTENT) ||
mimeType.equals(ClipDescription.MIMETYPE_TEXT_PLAIN) ||
mimeType.equals(ClipDescription.MIMETYPE_TEXT_URILIST) ) {
continue;
} else {
uriMimeType= mimeType;
break;
}
}
return uriMimeType;
}
public static String getMimeTypeFromUri(Context context, Uri uri) {
// return the MIME type of the Content URI or the file URI
return mimeType;
}

 

3. Do something with the dropped URI and return true for dealing with the ACTION_DROP action type only if URI is not null and URI has the valid mimeType.

public class InteractionReceiverActivityextends Activity {
public void onCreate( Bundle savedInstanceState) {
View v = findViewById(R.id.view_to_drop);
v.setOnDragListener(draglistener);
}
View.OnDragListenerdraglistener= new View.OnDragListener( ) {
@Override
public booleanonDrag(View v, DragEventevent) {
switch (event.getAction()) {
....
case DragEvent.ACTION_DROP:
return onDrop(v, event);
// Do something with the dropped Uri data.
//Return true only if the data is handled here
}
return false;
}
}
private boolean onDrop(DragEvent event) {
// Gets the item containing the dragged data
ClipDataclip = event.getClipData();
// Gets the text data from the item.
Uri uri= getUri(clip);
// Null check is essential, because clip data couldn’t include uri
if(uri!= null && hasValidMimeType(clip)) {
// Do something with the dropped Uri
// return true only if the uri is handled here
return true;
}
return false;
}
}

 

Navigation