Still Be Careful of Drag-and-Drop on Android 7.0

Back in June, I warned you about cross-app drag-and-drop on Android 7.0. While those who initiate drag-and-drop operations have to explicitly opt into those operations working across apps, drop targets have no equivalent mechanism. Your OnDragListener will be invoked for any drag-and-drop while your activity is visible, even if that drag-and-drop originates in some other app in a multi-window environment.

In that post, I suggested that using a non-null local state was a workaround:

  • In your own startDrag() or startDragAndDrop() calls, pass a non-null value for the “local state” Object

  • In onDrag(), see if the DragEvent has a null local state; if so, that drag-and-drop operation must have begun in another app, and so you can make decisions accordingly

Unfortunately, this does not work as well as I thought or as well as I had been led to believe.

The “local” in “local state” does not refer to an app or a process. Instead, it refers to a window. If two of your activities are visible in separate windows — perhaps you used FLAG_ACTIVITY_LAUNCH_ADJACENT, for example — the local state is lost in the drag-and-drop between those windows. Even if you think that you will not have two of your activities visible at one time, think again, as other apps can cause that to happen to you.

At this point, I have no idea how we can distinguish between a cross-app drag-and-drop and a cross-window drag-and-drop within the same app.