EditTextから/へのコピー/貼り付けを無効にする方法


131

私のアプリケーションには、ユーザーがテキストをEditTextフィールドにコピー/貼り付けできないようにする登録画面があります。コピー/貼り付け/ inputmethodおよびその他のオプションを示すコンテキストメニューが表示されないように、onLongClickListenerそれぞれにを設定しましEditTextた。したがって、ユーザーは編集フィールドにコピー/貼り付けできません。

 OnLongClickListener mOnLongClickListener = new OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            // prevent context menu from being popped up, so that user
            // cannot copy/paste from/into any EditText fields.
            return true;
        }
    };

ただし、ユーザーがAndroidのデフォルト以外のサードパーティ製キーボードを有効にしている場合に問題が発生します。このキーボードには、コピー/貼り付けのボタンがあるか、同じコンテキストメニューが表示される場合があります。では、そのシナリオでコピー/貼り付けを無効にするにはどうすればよいですか?

コピー/貼り付けする方法が他にもあるかどうか教えてください。(そしておそらくそれらを無効にする方法)

任意の助けいただければ幸いです。


「貼り付け」操作がIMEからのものである場合、通常のキーストロークと区別する標準的な方法はありません。試してみる1つのアイデアは、各キャラクターの到着間の時間を測定することです。時間が短すぎる場合、キャラクターは「貼り付け」操作から来ています。
BitBank

汚い油だそうです!一見の価値があります。
rDroid

1
android:longClickable = "false"を使用
Azay Gupta

回答:


112

APIレベル11以上を使用している場合は、コピー、貼り付け、切り取り、カスタムコンテキストメニューの表示を停止できます。

edittext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false;
            }

            public void onDestroyActionMode(ActionMode mode) {                  
            }

            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                return false;
            }

            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                return false;
            }
        });

onCreateActionMode(ActionMode、Menu)からfalseを返すと、アクションモードが開始されなくなります(すべて選択、切り取り、コピー、貼り付けアクション)。


1
13未満のAPIレベルはどうですか?
ジョナサン

1
どちらのコメントも理解しないでください。このサンプルはapi11 +で動作し、api11以前はIIRCをコピーアンドペーストしませんでした
scottyab

28
青色のカーソルインジケーターをタップすると、貼り付けボタンが表示されます。
2014年

8
また私のために働いていません。ダブルタップするとコピーペーストのメニューが表示されます。
Androidキラー

これは、この答えをチェックし、アンドロイド6.0上ではもう働いていないstackoverflow.com/questions/27869983/...
has19

132

最良の方法は以下を使用することです:

etUsername.setLongClickable(false);

58
または、単にxmlでandroid:longClickable="false":)
lomza '24年

19
青いカーソルインジケーターをタップすると、貼り付けボタンが表示されます。

16
これにより、ビューが長くクリック可能になるのを確実に防ぐことができますが、テキストをダブルタップして編集コントロールを要求することもできます。つまり、このソリューションは完全ではありません。あなたの目的のためにこれを覚えておいてください。
ケビン・グラント

1
また、キーボードショートカットは外部キーボードでも機能します(Ctrl + C)。
Oleg Vaskevich 14年

これはアイスクリームサンドイッチでは機能しません。テキストをダブルタップするだけでなく、ロングタップしてもクリップボードオプションを開くことができるためです。
Paul Wintz

44

EditTextの長押しを無効にすることでこれを行うことができます

それを実装するには、次の行をxmlに追加するだけです-

android:longClickable="false"

6
問題は、私のアプリユーザーがコピーと貼り付けのボタンを備えたサードパーティのキーボードを持っていることでした。
rDroid 2015

3
別の問題は、ダブルタップでテキストを選択すると、コピー/貼り付けが再び表示されることです
Nikola

37

以下を使用して、コピーアンドペースト機能を無効にできます。

textField.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
        return false;
    }

    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
        return false;
    }

    public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) {
        return false;
    }

    public void onDestroyActionMode(ActionMode actionMode) {
    }
});

textField.setLongClickable(false);
textField.setTextIsSelectable(false);

それがあなたのために働くことを願っています;-)


これは、上記の他の回答に基づいて私が最終的に得たまったく同じソリューションです。これは、他のケースでは処理されないエッジケースを処理するため、正しいソリューションとしてマークする必要があります
Andrew Hoefling

2
このオプションはコピーをブロックしますが、カーソルをクリックして貼り付けることもできます。
Mehul Kanzariya 2018年

12

すべてのバージョンでeditTextのカットコピーペーストを無効にする最良の方法を次に示します

if (android.os.Build.VERSION.SDK_INT < 11) {
        editText.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {

            @Override
            public void onCreateContextMenu(ContextMenu menu, View v,
                    ContextMenuInfo menuInfo) {
                // TODO Auto-generated method stub
                menu.clear();
            }
        });
    } else {
        editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                // TODO Auto-generated method stub
                return false;
            }

            public void onDestroyActionMode(ActionMode mode) {
                // TODO Auto-generated method stub

            }

            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // TODO Auto-generated method stub
                return false;
            }

            public boolean onActionItemClicked(ActionMode mode,
                    MenuItem item) {
                // TODO Auto-generated method stub
                return false;
            }
        });
    }

これは私にとってはうまくいきました、@ TargetApi(Build.VERSION_CODES.HONEYCOMB)を追加するだけでした
Sheepdogsheep

11

setCustomSelectionActionModeCallback無効にされたロングクリックソリューションに加えて、以下の画像のように、テキスト選択ハンドルがクリックされたときにPASTE / REPLACEメニューが表示されないようにする必要があります。

貼り付けメニュー付きのテキスト選択ハンドル

解決策はshow()、(ドキュメント化されていない)android.widget.EditorクラスのメソッドにPASTE / REPLACEメニューが表示されないようにすることです。メニューが表示される前に、へのチェックが行われif (!canPaste && !canSuggest) return;ます。これらの変数を設定するための基礎として使用される2つのメソッドは、どちらもEditTextクラス内にあります。

より完全な答えはここにあります


これは正しい完全なソリューションです
FireZenk

一部のデバイスでは、クリップボードの貼り付けオプションの代わりに表示され、貼り付けのみとして機能します。リンクをチェックしましたが、貼り付けはできますがクリップボードはできません。何か案が ?
リチャ

10

Kotlinソリューション:

fun TextView.disableCopyPaste() {
    isLongClickable = false
    setTextIsSelectable(false)
    customSelectionActionModeCallback = object : ActionMode.Callback {
        override fun onCreateActionMode(mode: ActionMode?, menu: Menu): Boolean {
            return false
        }

        override fun onPrepareActionMode(mode: ActionMode?, menu: Menu): Boolean {
            return false
        }

        override fun onActionItemClicked(mode: ActionMode?, item: MenuItem): Boolean {
            return false
        }

        override fun onDestroyActionMode(mode: ActionMode?) {}
    }
}

次に、単にこのメソッドを呼び出すことができますTextView

override fun onCreate() {
    priceEditText.disableCopyPaste()
}

1
こんにちは、私はこのアプローチを使用していますが、この部分のType mismatchこの説明Required:ActionMode.Callback! Found: でエラーが発生していますobject: ActionMode.Callback。なぜそれが機能しないかもしれないという考え?
Abdul Mateen

8

他のソリューションを使用して、API 26(Oreo)は、入力されたテキストを1回タップするだけでカーソルハンドルを表示し、メニューを表示できました。ソリューションの組み合わせだけが私の問題を解決できます。

public class CustomEditText extends EditText {

    public CustomEditText(Context context) {
        super(context);
        init();
    }

    public CustomEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        this.setCustomSelectionActionModeCallback(new BlockedActionModeCallback());
        this.setLongClickable(false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            this.setInsertionDisabled();
        }
        return super.onTouchEvent(event);
    }

    /**
    * This method sets TextView#Editor#mInsertionControllerEnabled field to false
    * to return false from the Editor#hasInsertionController() method to PREVENT showing
    * of the insertionController from EditText
    * The Editor#hasInsertionController() method is called in  Editor#onTouchUpEvent(MotionEvent event) method.
    */
    private void setInsertionDisabled() {
        try {
            Field editorField = TextView.class.getDeclaredField("mEditor");
            editorField.setAccessible(true);
            Object editorObject = editorField.get(this);

            Class editorClass = Class.forName("android.widget.Editor");
            Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
            mInsertionControllerEnabledField.setAccessible(true);
            mInsertionControllerEnabledField.set(editorObject, false);
        }
        catch (Exception ignored) {
            // ignore exception here
        }
    }

    @Override
    public boolean isSuggestionsEnabled() {
        return false;
    }

    private class BlockedActionModeCallback implements ActionMode.Callback {
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            return false;
        }

        public void onDestroyActionMode(ActionMode mode) {
        }
    }
}

5

ロングクリックでいくつかの機能を実行する必要があるため、ロングクリックを無効にしたくない場合は、trueを返すよりも優れたオプションです。

エディットテキストの長いクリックは次のようになります。

edittext.setOnLongClickListener(new View.OnLongClickListener() {
      @Override
      public boolean onLongClick(View v) {
            //  Do Something or Don't
            return true;
      }
});

ドキュメントのとおり、 「True」を返すと、長いクリックが処理されたため、デフォルトの操作を実行する必要がないことが示されます。

私はこれをAPIレベル16、22、25でテストしました。これがお役に立てば幸いです。


1
いいね。または、android:longClickable="false"XMLで設定するだけ
Alex Semeniuk

3

https://github.com/neopixl/PixlUIEditTextメソッドを提供します

myEditText.disableCopyAndPaste()

そしてそれは古いAPIで動作します


1
これは、stackoverflow.com / a / 22756538/3063884によって提供される半分のソリューションとまったく同じです。コードを参照してください:github.com/neopixl/PixlUI/blob/master/Library/src/com/neopixl/… ...この方法でも、クリップボードにテキストがある場合、テキスト選択ハンドラーが「PASTE」を表示することを妨げません。
CJBS 2015

3

ここに「貼り付け」ポップアップを無効にするハックがあります。EditTextメソッドをオーバーライドする必要があります:

@Override
public int getSelectionStart() {
    for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
        if (element.getMethodName().equals("canPaste")) {
            return -1;
        }
    }
    return super.getSelectionStart();
}

他のアクションについても同様です。


クリップボードの無効化について教えてください
リカ

3

私はこのソリューションをテストしましたが、これは機能します

    mSubdomainEditText.setLongClickable(false);
    mSubdomainEditText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

      public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
      }

      public void onDestroyActionMode(ActionMode mode) {
      }

      public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        return false;
      }

      public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return false;
      }
    });

1

クリップボードを読み取り、入力と「入力」が行われた時刻を確認します。クリップボードに同じテキストがあり、速すぎる場合は、貼り付けた入力を削除してください。


1

@Zain Ali、あなたの答えはAPI 11で動作します。私は、API 10でも実行できる方法を提案したかっただけです。私はプロジェクトAPIをそのバージョンで維持する必要があったので、2.3.3で利用可能な機能を常に試していて、それを実行する可能性がありました。以下のスニペットを共有します。私はコードをテストし、それは私のために働いていました。私は緊急にこのスニペットを行いました。可能な変更がある場合は、自由にコードを改善してください。

// A custom TouchListener is being implemented which will clear out the focus 
// and gain the focus for the EditText, in few milliseconds so the selection 
// will be cleared and hence the copy paste option wil not pop up.
// the respective EditText should be set with this listener 
// tmpEditText.setOnTouchListener(new MyTouchListener(tmpEditText, tmpImm));

public class MyTouchListener implements View.OnTouchListener {

    long click = 0;
    EditText mEtView;
    InputMethodManager imm;

    public MyTouchListener(EditText etView, InputMethodManager im) {
        mEtView = etView;
        imm = im;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            long curr = System.currentTimeMillis();
            if (click !=0 && ( curr - click) < 30) {

                mEtView.setSelected(false);
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mEtView.setSelected(true);
                        mEtView.requestFocusFromTouch();
                        imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                    }
                },25);

            return true;
            }
            else {
                if (click == 0)
                    click = curr;
                else
                    click = 0;
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mEtView.requestFocusFromTouch();
                        mEtView.requestFocusFromTouch();
                        imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                    }
                },25);
            return true;
            }

        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            mEtView.setSelected(false);
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mEtView.setSelected(true);
                    mEtView.requestFocusFromTouch();
                    mEtView.requestFocusFromTouch();
                    imm.showSoftInput(mEtView, InputMethodManager.RESULT_SHOWN);
                }
            },25);
            return true;
        }
        return false;
    }

1

解決策は非常に簡単です

public class MainActivity extends AppCompatActivity {

EditText et_0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et_0 = findViewById(R.id.et_0);

    et_0.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            //to keep the text selection capability available ( selection cursor)
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            //to prevent the menu from appearing
            menu.clear();
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {

        }
    });
   }
}

-------->プレビュー<---------


1

次のカスタムクラスを試してコピーして貼り付けてください Edittext

public class SegoeUiEditText extends AppCompatEditText {
private final Context context;


@Override
public boolean isSuggestionsEnabled() {
    return false;
}
public SegoeUiEditText(Context context) {
    super(context);
    this.context = context;
    init();
}

public SegoeUiEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    init();
}

public SegoeUiEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}


private void setFonts(Context context) {
    this.setTypeface(Typeface.createFromAsset(context.getAssets(), "Fonts/Helvetica-Normal.ttf"));
}

private void init() {

        setTextIsSelectable(false);
        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
        this.setLongClickable(false);

}
@Override
public int getSelectionStart() {

    for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
        if (element.getMethodName().equals("canPaste")) {
            return -1;
        }
    }
    return super.getSelectionStart();
}
/**
 * Prevents the action bar (top horizontal bar with cut, copy, paste, etc.) from appearing
 * by intercepting the callback that would cause it to be created, and returning false.
 */
private class ActionModeCallbackInterceptor implements ActionMode.Callback, android.view.ActionMode.Callback {
    private final String TAG = SegoeUiEditText.class.getSimpleName();

    public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; }
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; }
    public void onDestroyActionMode(ActionMode mode) {}

    @Override
    public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
        menu.clear();
        return false;
    }

    @Override
    public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
        return false;
    }

    @Override
    public void onDestroyActionMode(android.view.ActionMode mode) {

    }
}

}


1

クリップボード付きのスマホの場合、こうやって防ぐことが可能です。

editText.setFilters(new InputFilter[]{new InputFilter() {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.length() > 1) {
                return "";
            }  return null;
        }
    }});


0

不要な文字が入力されないように入力フィルターを作成すると、そのような文字を編集テキストに貼り付けても効果がないことがわかりました。このようにして私の問題も解決します。



0

私にとってうまくいった解決策は、カスタムEdittextを作成し、次のメソッドをオーバーライドすることでした:

public class MyEditText extends EditText {

private int mPreviousCursorPosition;

@Override
protected void onSelectionChanged(int selStart, int selEnd) {
    CharSequence text = getText();
    if (text != null) {
        if (selStart != selEnd) {
            setSelection(mPreviousCursorPosition, mPreviousCursorPosition);
            return;
        }
    }
    mPreviousCursorPosition = selStart;
    super.onSelectionChanged(selStart, selEnd);
}

}


0

使ってみてください。

myEditext.setCursorVisible(false);

       myEditext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            // TODO Auto-generated method stub
            return false;
        }

        public void onDestroyActionMode(ActionMode mode) {
            // TODO Auto-generated method stub

        }

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // TODO Auto-generated method stub
            return false;
        }

        public boolean onActionItemClicked(ActionMode mode,
                MenuItem item) {
            // TODO Auto-generated method stub
            return false;
        }
    });

0

Kotlinでソリューションを探している人は、以下のクラスをカスタムウィジェットとして使用し、xmlで使用します。

SecureEditTextクラス:TextInputEditText {

/** This is a replacement method for the base TextView class' method of the same name. This method
 * is used in hidden class android.widget.Editor to determine whether the PASTE/REPLACE popup
 * appears when triggered from the text insertion handle. Returning false forces this window
 * to never appear.
 * @return false
 */
override fun isSuggestionsEnabled(): Boolean {
    return false
}

override fun getSelectionStart(): Int {
    for (element in Thread.currentThread().stackTrace) {
        if (element.methodName == "canPaste") {
            return -1
        }
    }
    return super.getSelectionStart()
}

public override fun onSelectionChanged(start: Int, end: Int) {

    val text = text
    if (text != null) {
        if (start != text.length || end != text.length) {
            setSelection(text.length, text.length)
            return
        }
    }

    super.onSelectionChanged(start, end)
}

companion object {
    private val EDITTEXT_ATTRIBUTE_COPY_AND_PASTE = "isCopyPasteDisabled"
    private val PACKAGE_NAME = "http://schemas.android.com/apk/res-auto"
}

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
    disableCopyAndPaste(context, attrs)
}

/**
 * Disable Copy and Paste functionality on EditText
 *
 * @param context Context object
 * @param attrs   AttributeSet Object
 */
private fun disableCopyAndPaste(context: Context, attrs: AttributeSet) {
    val isDisableCopyAndPaste = attrs.getAttributeBooleanValue(
        PACKAGE_NAME,
        EDITTEXT_ATTRIBUTE_COPY_AND_PASTE, true
    )
    if (isDisableCopyAndPaste && !isInEditMode()) {
        val inputMethodManager =
            context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        this.setLongClickable(false)
        this.setOnTouchListener(BlockContextMenuTouchListener(inputMethodManager))
    }
}

/**
 * Perform Focus Enabling Task to the widget with the help of handler object
 * with some delay
 * @param inputMethodManager is used to show the key board
 */
private fun performHandlerAction(inputMethodManager: InputMethodManager) {
    val postDelayedIntervalTime: Long = 25
    Handler().postDelayed(Runnable {
        this@SecureEditText.setSelected(true)
        this@SecureEditText.requestFocusFromTouch()
        inputMethodManager.showSoftInput(
            this@SecureEditText,
            InputMethodManager.RESULT_SHOWN
        )
    }, postDelayedIntervalTime)
}

/**
 * Class to Block Context Menu on double Tap
 * A custom TouchListener is being implemented which will clear out the focus
 * and gain the focus for the EditText, in few milliseconds so the selection
 * will be cleared and hence the copy paste option wil not pop up.
 * the respective EditText should be set with this listener
 *
 * @param inputMethodManager is used to show the key board
 */
private inner class BlockContextMenuTouchListener internal constructor(private val inputMethodManager: InputMethodManager) :
    View.OnTouchListener {
    private var lastTapTime: Long = 0
    val TIME_INTERVAL_BETWEEN_DOUBLE_TAP = 30
    override fun onTouch(v: View, event: MotionEvent): Boolean {
        if (event.getAction() === MotionEvent.ACTION_DOWN) {
            val currentTapTime = System.currentTimeMillis()
            if (lastTapTime != 0L && currentTapTime - lastTapTime < TIME_INTERVAL_BETWEEN_DOUBLE_TAP) {
                this@SecureEditText.setSelected(false)
                performHandlerAction(inputMethodManager)
                return true
            } else {
                if (lastTapTime == 0L) {
                    lastTapTime = currentTapTime
                } else {
                    lastTapTime = 0
                }
                performHandlerAction(inputMethodManager)
                return true
            }
        } else if (event.getAction() === MotionEvent.ACTION_MOVE) {
            this@SecureEditText.setSelected(false)
            performHandlerAction(inputMethodManager)
        }
        return false
    }
}

}


0

Kotlin言語で拡張機能を追加しました。

fun EditText.disableTextSelection() {
    this.setCustomSelectionActionModeCallback(object : android.view.ActionMode.Callback {
        override fun onActionItemClicked(mode: android.view.ActionMode?, item: MenuItem?): Boolean {
            return false
        }
        override fun onCreateActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
            return false
        }
        override fun onPrepareActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
            return false
        }
        override fun onDestroyActionMode(mode: android.view.ActionMode?) {
        }
    })
}

あなたはこのようにそれを使うことができます:

edit_text.disableTextSelection()

あなたのxmlの行の下にも追加されました:

                android:longClickable="false"
                android:textIsSelectable="false"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.