Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ vars = {
# Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS.
# You can use //tools/dart/create_updated_flutter_deps.py to produce
# updated revision list of existing dependencies.
'dart_revision': '1d923a386d7a9f384435a2b4c1287b2937504566',
'dart_revision': 'ecf9ce8ef42de11033801b2870e8b310c3722902',

# WARNING: DO NOT EDIT MANUALLY
# The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import io.flutter.Log;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import java.io.FileNotFoundException;
import java.util.List;

/** Android implementation of the platform plugin. */
Expand All @@ -29,6 +31,7 @@ public class PlatformPlugin {
private final PlatformChannel platformChannel;
private PlatformChannel.SystemChromeStyle currentTheme;
private int mEnabledOverlays;
private static final String TAG = "PlatformPlugin";

@VisibleForTesting
final PlatformChannel.PlatformMessageHandler mPlatformMessageHandler =
Expand Down Expand Up @@ -280,11 +283,28 @@ private void popSystemNavigator() {
private CharSequence getClipboardData(PlatformChannel.ClipboardContentFormat format) {
ClipboardManager clipboard =
(ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = clipboard.getPrimaryClip();
if (clip == null) return null;

if (format == null || format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
return clip.getItemAt(0).coerceToText(activity);
if (!clipboard.hasPrimaryClip()) return null;

try {
ClipData clip = clipboard.getPrimaryClip();
if (clip == null) return null;
if (format == null || format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
ClipData.Item item = clip.getItemAt(0);
if (item.getUri() != null)
activity.getContentResolver().openTypedAssetFileDescriptor(item.getUri(), "text/*", null);
return item.coerceToText(activity);
}
} catch (SecurityException e) {
Log.w(
TAG,
"Attempted to get clipboard data that requires additional permission(s).\n"
+ "See the exception details for which permission(s) are required, and consider adding them to your Android Manifest as described in:\n"
+ "https://developer.android.com/guide/topics/permissions/overview",
e);
return null;
} catch (FileNotFoundException e) {
return null;
}

return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package io.flutter.plugin.platform;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.media.RingtoneManager;
import android.net.Uri;
import android.view.View;
import android.view.Window;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.embedding.engine.systemchannels.PlatformChannel.ClipboardContentFormat;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
Expand Down Expand Up @@ -38,6 +46,45 @@ public void itIgnoresNewHapticEventsOnOldAndroidPlatforms() {
platformPlugin.vibrateHapticFeedback(PlatformChannel.HapticFeedbackType.SELECTION_CLICK);
}

@Config(sdk = 29)
@Test
public void platformPlugin_getClipboardData() throws IOException {
ClipboardManager clipboardManager =
RuntimeEnvironment.application.getSystemService(ClipboardManager.class);

View fakeDecorView = mock(View.class);
Window fakeWindow = mock(Window.class);
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
Activity fakeActivity = mock(Activity.class);
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
when(fakeActivity.getSystemService(Context.CLIPBOARD_SERVICE)).thenReturn(clipboardManager);
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);

ClipboardContentFormat clipboardFormat = ClipboardContentFormat.PLAIN_TEXT;
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
ClipData clip = ClipData.newPlainText("label", "Text");
clipboardManager.setPrimaryClip(clip);
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));

ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver();
Uri uri = Uri.parse("content://media/external_primary/images/media/");
clip = ClipData.newUri(contentResolver, "URI", uri);
clipboardManager.setPrimaryClip(clip);
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));

uri =
RingtoneManager.getActualDefaultRingtoneUri(
RuntimeEnvironment.application.getApplicationContext(), RingtoneManager.TYPE_RINGTONE);
clip = ClipData.newUri(contentResolver, "URI", uri);
clipboardManager.setPrimaryClip(clip);
String uriData =
platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat).toString();
InputStream uriInputStream = contentResolver.openInputStream(uri);
InputStream dataInputStream = new ByteArrayInputStream(uriData.getBytes());
assertEquals(dataInputStream.read(), uriInputStream.read());
}

@Test
public void platformPlugin_hasStrings() {
ClipboardManager clipboardManager =
Expand Down