The clipboard code that works for API levels < 11 crashes on devices with API levels >= 11.
The clipboard code that work for API level >= 11 crashes on devices with API levels < 11.
I can not compile code for both versions because they have conflicting import requirements.
One needs:
import android.text.ClipboardManager;
while the other needs:
import android.content.ClipboardManager;
Surely there is a way write some code that will work on both sides of API level 11. I just can't figure it out.
***Edited (Since I can't answer my own question) *******
I found the problem. The exception message says, "Can't create handler inside a thread that has not called Looper.prepare()."
Apparently I have to jump through some more hoops since I am executing this code from an Async task.
The clipboard code that works for API levels < 11 crashes on devices with API levels >= 11.
This sample project works quite nicely on API levels before and after 11. I just retested it on Android 2.3 (Nexus One) and Android 4.0 (Nexus S).
The clipboard code that work for API level >= 11 crashes on devices with API levels < 11.
That is not surprising. If you are referring to classes or methods that do not exist in older versions of Android, you will get a VerifyError
or similar crashes.
I can not compile code for both versions because they have conflicting import requirements.
Not really.
One needs: import android.text.ClipboardManager;
That works on all API levels.
while the other needs: import android.content.ClipboardManager;
That was added to API Level 11. If your app will only run on API Level 11 or higher, use this class (method signatures are all the same IIRC).
I recently faced a similar problem.
Here's how I handled it.
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB){
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label", "Text to Copy");
clipboard.setPrimaryClip(clip);
} else{
android.text.ClipboardManager clipboard = (android.text.ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
clipboard.setText("Text to Copy");
}
Toast.makeText(getApplicationContext(), "Text copied to clipboard", Toast.LENGTH_SHORT).show();
I'm not entirely sure if the first if block is necessary. But I'd rather not take a chance :)
To avoid the exception
[FATAL EXCEPTION: GLThread 6132 java.lang.RuntimeException:
Can't create handler inside thread that has not called Looper.prepare() ],
-> just create the ClipboardManager
once at startup, for example in your onCreate()
method and use it anytime in a separate function.
tested working on 2.3.3 and 4.0.3:
import android.text.ClipboardManager;
import android.content.ClipData;
..
public class myActivity extends Activity
{
private static ClipboardManager m_ClipboardManager;
@Override
protected void onCreate(..)
{
...
m_ClipboardManager = (ClipboardManager) m_sInstance.getSystemService(Context.CLIPBOARD_SERVICE);
}
public static void myCopyToClipBoard(String sTxt)
{
m_ClipboardManager.setText(sTxt);
}
}
Write yourself your own Clipboard compat class, for example:
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.Context;
import android.net.Uri;
public class ClipboardCompat {
private android.content.ClipboardManager currentCM=null;
private android.text.ClipboardManager legacyCM=null;
public ClipboardCompat() {
if(android.os.Build.VERSION.SDK_INT >= 11 && currentCM == null) {
currentCM = (android.content.ClipboardManager)
[getsomecontext].getSystemService(Context.CLIPBOARD_SERVICE);
}
else if(legacyCM == null)
{
legacyCM = (android.content.ClipboardManager)
[getsomecontext].getSystemService(Context.CLIPBOARD_SERVICE);
}
}
@SuppressLint("NewApi")
public String getText() {
if(currentCM!=null) {
try{
return currentCM.getPrimaryClip().getItemAt(0).getText().toString();
} catch (NullPointerException e) {
return null;
}
}
else
{
try{
return legacyCM.getText().toString();
} catch (NullPointerException e) {
return null;
}
}
}
@SuppressLint("NewApi")
public Uri getUri() {
if(currentCM!=null) {
try{
return currentCM.getPrimaryClip().getItemAt(0).getUri();
} catch (NullPointerException e) {
return null;
}
}
else
{
return null;
}
}
@SuppressLint("NewApi")
public void set(String name, String s) {
if(currentCM!=null) {
ClipData clip = ClipData.newPlainText(name, s);
currentCM.setPrimaryClip(clip);
}
else
{
legacyCM.setText(s);
}
}
@SuppressLint("NewApi")
public void set(String name, Uri u) {
if(currentCM!=null) {
ClipData clip = ClipData.newRawUri(name, u);
currentCM.setPrimaryClip(clip);
}
else
{
legacyCM.setText(u.toString());
}
}
}