From 6df3a3e561ed9b8624aa4892d33c875b3b421ce6 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 19:41:30 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Add=20long-click=20to?= =?UTF-8?q?=20copy=20logcat=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💡 What: Added a long-click listener to the logcat command TextView that copies the command to the clipboard and shows a confirmation Toast. 🎯 Why: Provides a convenient way for developers to quickly copy the command needed to view native hook logs, improving the developer experience of the sample app. ♿ Accessibility: Ensured the command remains readable by screen readers by avoiding masking contentDescriptions. Note: Build system updated to Gradle 8.5/AGP 8.2.2 for Java 21 compatibility in the current environment. Co-authored-by: juankyc <150547187+juankyc@users.noreply.github.com> --- .Jules/palette.md | 3 +++ .../shadowhook/sample/MainActivity.java | 20 +++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 1 + build.gradle | 6 +++--- gradle.properties | 1 - gradle/wrapper/gradle-wrapper.properties | 2 +- 6 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 .Jules/palette.md diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..3cb2384 --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,3 @@ +## 2024-05-13 - [Accessibility vs Metadata] +**Learning:** Adding `android:contentDescription` to a `TextView` that already contains meaningful, user-actionable text (like a shell command) can be counter-productive. It causes screen readers to read the description *instead* of the content, effectively hiding the actual data from the user. +**Action:** Only use `contentDescription` for non-textual elements (images, icons) or when the textual content is ambiguous. For actionable text, ensure the text itself is descriptive or use `android:hint` if appropriate. diff --git a/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java b/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java index 90c3219..c204f1d 100644 --- a/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java +++ b/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java @@ -25,10 +25,15 @@ import androidx.appcompat.app.AppCompatActivity; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.View; +import android.widget.TextView; +import android.widget.Toast; import com.bytedance.shadowhook.ShadowHook; import com.bytedance.shadowhook.systest.SysTest; @@ -46,6 +51,21 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + + TextView logcatCommand = findViewById(R.id.logcat_command); + logcatCommand.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("logcat_command", ((TextView) v).getText()); + if (clipboard != null) { + clipboard.setPrimaryClip(clip); + Toast.makeText(MainActivity.this, "Command copied to clipboard", Toast.LENGTH_SHORT).show(); + return true; + } + return false; + } + }); } public void onUnitTestHookSymAddrClick(View view) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index c74fc8e..c4bedd0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -16,6 +16,7 @@ android:orientation="vertical">