如何在Android中将文本复制到剪贴板?

459
有人可以告诉我怎样在按下按钮时将特定TextView中的文本复制到剪贴板吗?
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainpage);
    textView = (TextView) findViewById(R.id.textview);
    copyText = (Button) findViewById(R.id.bCopy);
    copyText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            
            ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
            String getstring = textView.getText().toString();
            
            // Help to continue :)
        }
    });
}

当按钮bCopy被按下时,我想要将TextView中的文本复制到剪贴板。

2
可能是重复的问题:如何在我的Android应用程序中以编程方式复制文本? - Shabbir Dhangot
https://stackoverflow.com/q/48791271/9274175 请将答案复制 - Yash Kale
32个回答

826

使用ClipboardManager

 ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 
 ClipData clip = ClipData.newPlainText(label, text);
 clipboard.setPrimaryClip(clip);

确保您已经导入了android.content.ClipboardManager而不是android.text.ClipboardManager。后者已经过时。 请查看此链接获取更多信息。


5
仅适用于API11及以上版本,不适用于GB及以下版本。 - Javier
86
“标签”用于什么? - android developer
32
"标签"参数的解释:https://dev59.com/TlwX5IYBdhLWcg3w8TMf - smg
3
那么这更适合开发人员?但为什么它说是向用户展示的? - android developer
22
在AndroidX中,实际上变成了ClipboardManager clipboard = getSystemService(getContext(), ClipboardManager.class); - HoratioCain
显示剩余4条评论

93

以下是将文本复制到剪贴板的方法:

private void setClipboard(Context context, String text) {
  if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
    android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
    clipboard.setText(text);
  } else {
    android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
    android.content.ClipData clip = android.content.ClipData.newPlainText("Copied Text", text);
    clipboard.setPrimaryClip(clip);
  }
}

这种方法适用于所有的安卓设备。


2
我不明白“context”的含义。你能举个例子说明如何正确调用该方法吗?谢谢。 - E_Blue
嘿,伙计,需要在片段中提供上下文才能调用getSystemService。 - vuhung3990
@E_Blue context.getSystemService(Context.CLIPBOARD_SERVICE) 真的吗? - androidStud
1
@E_Blue 看起来你是一个天真的安卓开发者,正在询问关于上下文的问题。这也不是问题,但请注意你的语气,并进行一些研究和调查。 - androidStud

69

作为一个方便的 Kotlin 扩展:

fun Context.copyToClipboard(text: CharSequence){
    val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    val clip = ClipData.newPlainText("label",text)
    clipboard.setPrimaryClip(clip)
}

更新:

如果您使用ContextCompat,则应使用:

ContextCompat.getSystemService(this, ClipboardManager::class.java)

5
API现在已更改为clipboardManager = getSystemService(context, ClipboardManager::class.java) - Per Christian Henden
2
它实际上已更改为context.getSystemService(ClipboardManager::class.java),您指向了一个ContextCompat签名,不是吗?感谢反馈。 - crgarridos
3
将最后一行改为 clipboard.setPrimaryClip(clip)。 - CodeSmith

61

昨天我写了这个类。拿去用吧,它适用于所有API版本

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.util.Log;
import de.lochmann.nsafirewall.R;

public class MyClipboardManager {

    @SuppressLint("NewApi")
    @SuppressWarnings("deprecation")
    public boolean copyToClipboard(Context context, String text) {
        try {
            int sdk = android.os.Build.VERSION.SDK_INT;
            if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
                android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
                        .getSystemService(context.CLIPBOARD_SERVICE);
                clipboard.setText(text);
            } else {
                android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context
                        .getSystemService(context.CLIPBOARD_SERVICE);
                android.content.ClipData clip = android.content.ClipData
                        .newPlainText(
                                context.getResources().getString(
                                        R.string.message), text);
                clipboard.setPrimaryClip(clip);
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @SuppressLint("NewApi")
    public String readFromClipboard(Context context) {
        int sdk = android.os.Build.VERSION.SDK_INT;
        if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
            android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context
                    .getSystemService(context.CLIPBOARD_SERVICE);
            return clipboard.getText().toString();
        } else {
            ClipboardManager clipboard = (ClipboardManager) context
                    .getSystemService(Context.CLIPBOARD_SERVICE);

            // Gets a content resolver instance
            ContentResolver cr = context.getContentResolver();

            // Gets the clipboard data from the clipboard
            ClipData clip = clipboard.getPrimaryClip();
            if (clip != null) {

                String text = null;
                String title = null;

                // Gets the first item from the clipboard data
                ClipData.Item item = clip.getItemAt(0);

                // Tries to get the item's contents as a URI pointing to a note
                Uri uri = item.getUri();

                // If the contents of the clipboard wasn't a reference to a
                // note, then
                // this converts whatever it is to text.
                if (text == null) {
                    text = coerceToText(context, item).toString();
                }

                return text;
            }
        }
        return "";
    }

    @SuppressLint("NewApi")
    public CharSequence coerceToText(Context context, ClipData.Item item) {
        // If this Item has an explicit textual value, simply return that.
        CharSequence text = item.getText();
        if (text != null) {
            return text;
        }

        // If this Item has a URI value, try using that.
        Uri uri = item.getUri();
        if (uri != null) {

            // First see if the URI can be opened as a plain text stream
            // (of any sub-type). If so, this is the best textual
            // representation for it.
            FileInputStream stream = null;
            try {
                // Ask for a stream of the desired type.
                AssetFileDescriptor descr = context.getContentResolver()
                        .openTypedAssetFileDescriptor(uri, "text/*", null);
                stream = descr.createInputStream();
                InputStreamReader reader = new InputStreamReader(stream,
                        "UTF-8");

                // Got it... copy the stream into a local string and return it.
                StringBuilder builder = new StringBuilder(128);
                char[] buffer = new char[8192];
                int len;
                while ((len = reader.read(buffer)) > 0) {
                    builder.append(buffer, 0, len);
                }
                return builder.toString();

            } catch (FileNotFoundException e) {
                // Unable to open content URI as text... not really an
                // error, just something to ignore.

            } catch (IOException e) {
                // Something bad has happened.
                Log.w("ClippedData", "Failure loading text", e);
                return e.toString();

            } finally {
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException e) {
                    }
                }
            }

            // If we couldn't open the URI as a stream, then the URI itself
            // probably serves fairly well as a textual representation.
            return uri.toString();
        }

        // Finally, if all we have is an Intent, then we can just turn that
        // into text. Not the most user-friendly thing, but it's something.
        Intent intent = item.getIntent();
        if (intent != null) {
            return intent.toUri(Intent.URI_INTENT_SCHEME);
        }

        // Shouldn't get here, but just in case...
        return "";
    }

}

“coerceToText” 是什么意思?另外,是否可以将其他类型的数据(例如位图)复制/粘贴到剪贴板上? - android developer
1
@A.S. 为什么你自己写了 corceToText 方法?它已经在 API 中可用,参见 https://developer.android.com/reference/android/content/ClipData.Item.html#coerceToText%28android.content.Context%29。 - Hardik
但我认为开发人员有时间停止支持API17之前的东西。老式设备剩下的不多,它们也不倾向于下载新应用程序。例如,我在我的帆船上使用古老的设备进行导航,其他所有东西都被删除了。如果不小心把这样的设备扔到海里,我也不介意。 - Jan Bergström

44

针对Jetpack Compose

val localClipboardManager = LocalClipboardManager.current
localClipboardManager.setText(AnnotatedString("Your text here"))

15

只需使用此方法。它仅适用于Android API >= 11,在此之前您需要使用ClipData。

ClipboardManager _clipboard = (ClipboardManager) _activity.getSystemService(Context.CLIPBOARD_SERVICE);
_clipboard.setText(YOUR TEXT);

希望它能对你有所帮助 :)

[更新于3/19/2015]正如Ujjwal Singh所说,方法setText现在已被弃用,你应该使用文档建议的setPrimaryClip(clipData)


1
这是我的变量名称。如果您在Activity中,请使用(ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE); _clipboard.setText(YOUR TEXT); - Ektos974
1
已弃用 - 请勿使用 setText,请使用 ClipData + setPrimaryClip - Ujjwal Singh
1
对我来说,当使用setPrimaryClip时也会显示错误。 - Praneeth

14

在 Kotlin 中可以这样做:

var clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
var clip = ClipData.newPlainText("label", file.readText())
clipboard.setPrimaryClip = clip

file.readText()是您的输入字符串。


2
在Kotlin中,从API Level 29开始,应该使用setPrimaryClip代替primaryClip - davee44

12

2021年的Kotlin扩展函数:

fun Context.copyToClipboard(text: CharSequence){
    val clipboard = ContextCompat.getSystemService(this,ClipboardManager::class.java)
    clipboard?.setPrimaryClip(ClipData.newPlainText("",text))
}

8
请使用这段代码。
   private ClipboardManager myClipboard;
   private ClipData myClip;
   TextView textView;
   Button copyText;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainpage);
    textView = (TextView) findViewById(R.id.textview);
    copyText = (Button) findViewById(R.id.bCopy);
    myClipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);

    copyText.setOnClickListener(new View.OnClickListener() {


        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub


           String text = textView.getText().toString();
           myClip = ClipData.newPlainText("text", text);
           myClipboard.setPrimaryClip(myClip);
           Toast.makeText(getApplicationContext(), "Text Copied", 
           Toast.LENGTH_SHORT).show(); 
        }
    });
}

非常感谢,它非常易于使用。 - iamkdblue

7
使用此函数来复制到剪贴板。
public void copyToClipboard(String copyText) {
    int sdk = android.os.Build.VERSION.SDK_INT;
    if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
        android.text.ClipboardManager clipboard = (android.text.ClipboardManager)
                getSystemService(Context.CLIPBOARD_SERVICE);
        clipboard.setText(copyText);
    } else {
        android.content.ClipboardManager clipboard = (android.content.ClipboardManager)
                getSystemService(Context.CLIPBOARD_SERVICE);
        android.content.ClipData clip = android.content.ClipData
                .newPlainText("Your OTP", copyText);
        clipboard.setPrimaryClip(clip);
    }
    Toast toast = Toast.makeText(getApplicationContext(),
            "Your OTP is copied", Toast.LENGTH_SHORT);
    toast.setGravity(Gravity.BOTTOM | Gravity.RIGHT, 50, 50);
    toast.show();
    //displayAlert("Your OTP is copied");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接