Intent.ACTION_PROCESS_TEXT实现摘抄功能

版权声明:个人原创,欢迎转载。 https://blog.csdn.net/chuyangchangxi/article/details/83715052

一、实现效果

Android6.0以上使用Intent.ACTION_PROCESS_TEXT实现摘抄功能,理论上能摘抄10万字符。

TextView实际测试达到理论值为10万字符;

浏览器(Chrome、系统浏览器)实际测试文本长度不超过1000个字符;

测试机型:坚果Pro2,Android7.1.1

ACTION_PROCESS_TEXT实现摘抄功能

二、下载地址

演示APK

ExtractActivity

演示项目工程

三、使用方式

  • AndroidManifest.xml中添加Intent-Filter
<activity android:name=".ExtractActivity"
          android:label="摘抄"
          android:theme="@style/AppTheme.Transparent">
    <intent-filter>
        <action android:name="android.intent.action.PROCESS_TEXT" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
</activity>
  • 获取数据
CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT);

另外,可以通过Intent.EXTRA_PROCESS_TEXT_READONLY判断是否只读,非只读文本,可以通过setResult返回处理后的文本。

四、代码分析

  • Editor

TextView中通过Editor创建了弹出菜单。

private void updateAssistMenuItems(Menu menu)
    
private int createAssistMenuItemPendingIntentRequestCode()
    
private boolean shouldEnableAssistMenuItems()
    
private boolean onAssistMenuItemClicked(MenuItem assistMenuItem)

最终的选择文本

private boolean fireIntent(Intent intent) {
    if (intent != null && Intent.ACTION_PROCESS_TEXT.equals(intent.getAction())) {
        String selectedText = mTextView.getSelectedText();
        selectedText = TextUtils.trimToParcelableSize(selectedText);
        intent.putExtra(Intent.EXTRA_PROCESS_TEXT, selectedText);
        mEditor.mPreserveSelection = true;
        mTextView.startActivityForResult(intent, TextView.PROCESS_TEXT_REQUEST_CODE);
        return true;
    }
    return false;
}

理论上100K的字符数

private static final int PARCEL_SAFE_TEXT_LENGTH = 100000;

@Nullable
public static <T extends CharSequence> T trimToParcelableSize(@Nullable T text) {
    return trimToSize(text, PARCEL_SAFE_TEXT_LENGTH);
}
  • AppCompatTextViewAppCompatEditText

Editor中创建的弹出菜单项,在AppCompatTextViewAppCompatEditText中被调整过,直接的结果是MenuItemgroupIdID_ASSIST变成MENU.NONE

public class AppCompatTextView extends TextView implements TintableBackgroundView,
        AutoSizeableTextView {

	@Override
    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
        super.setCustomSelectionActionModeCallback(TextViewCompat
                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
    }            
            
}
public class AppCompatEditText extends EditText implements TintableBackgroundView {
    
    @Override
    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
        super.setCustomSelectionActionModeCallback(TextViewCompat
                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
    }
    
}
@RestrictTo(LIBRARY_GROUP)
@NonNull
public static ActionMode.Callback wrapCustomSelectionActionModeCallback(
    @NonNull final TextView textView,
    @NonNull final ActionMode.Callback callback) {
    if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27
        || callback instanceof OreoCallback) {
        // If the bug does not affect the current SDK version, or if
        // the callback was already wrapped, no need to wrap it.
        return callback;
    }
    // A bug in O and O_MR1 causes a number of options for handling the ACTION_PROCESS_TEXT
    // intent after selection to not be displayed in the menu, although they should be.
    // Here we fix this, by removing the menu items created by the framework code, and
    // adding them (and the missing ones) back correctly.
    return new OreoCallback(callback, textView);
}
// Populate the menu again with the ACTION_PROCESS_TEXT handlers.
final List<ResolveInfo> supportedActivities =
    getSupportedActivities(context, packageManager);
for (int i = 0; i < supportedActivities.size(); ++i) {
    final ResolveInfo info = supportedActivities.get(i);
    menu.add(Menu.NONE, Menu.NONE,
             MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i,
             info.loadLabel(packageManager))
        .setIntent(createProcessTextIntentForResolveInfo(info, mTextView))
        .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}

五、参考资料

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0116/3877.html

猜你喜欢

转载自blog.csdn.net/chuyangchangxi/article/details/83715052