Android 应用程序中的系统小部件是否可配置?

Are Android system widgets within app configurable?

当我按下其中一个音量硬件按钮时,Android 的系统 会显示一个图示。当然,当我在我的应用程序中按下时也会发生这种情况。

是否可以配置这些 Android 系统内容的样式,例如音量?或者至少当我在我的应用程序中打开这些系统内容时?

编辑:按照评论中的建议,我已经覆盖了 onKeyDown,但 adjustStreamVolume 仅在 0 和 1 之间切换。

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
    when (event?.keyCode) {
        KeyEvent.KEYCODE_VOLUME_UP -> {
            audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE)
            return true
        }
        KeyEvent.KEYCODE_VOLUME_DOWN -> {
            audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE)
            return true
        }
        else -> {
            return super.onKeyDown(keyCode, event)
        }
    }
}

streamVolume 确实没有增加。 不幸的是,当我连续按下 Volume_up 时,'getStreamVolume()' 值仍然是 t 1

音量对话框

对于音量,用自定义对话框替换音量对话框非常容易,从 android-hide-volume-change-bar-from-device 开始,您可以将其替换为简单的东西,例如 activity 中的进度条,因为 Android 为其提供一个接口。

通知对话框

您还可以(如果您非常有动力)自定义显示传入的通知。您将需要一个实现 NotificationListenerService 运行 的服务,它必须拦截通知,并将它们发送到主 activity 以按照您想要的方式显示它们。

其他对话框

其他的,例如电源菜单,由于显而易见的原因将无法更改。

结论

没有root权限不能修改android系统的样式,因为它是在系统app中编码的。

Android 为您提供了改变其行为的不同方式,但它有其局限性。

这里有一个卷的例子:

main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ProgressBar
        android:id="@+id/progress_horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>

</androidx.constraintlayout.widget.ConstraintLayout> 

MainActivity.java

public class MainActivity extends AppCompatActivity {

    AudioManager manager;
    ProgressBar progressBar;

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

        manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        progressBar = findViewById(R.id.progress_horizontal);
        updateVolume();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (event.getKeyCode()) {
            case KeyEvent.KEYCODE_VOLUME_UP:
                updateVolume();
                manager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
                        AudioManager.ADJUST_RAISE,
                        AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                return true;
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                updateVolume();
                manager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
                        AudioManager.ADJUST_LOWER,
                        AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
                return true;

            default:
                return super.onKeyDown(keyCode, event);
        }
    }

    private void updateVolume()
    {
        int currentVolume = manager.getStreamVolume(AudioManager.STREAM_MUSIC);
        int maxVolume = manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

        progressBar.setProgress((int) ((float) currentVolume/maxVolume*100));
    }
}

编辑

有人说原来的音量条还能看得见。 我直接在我的S10 Android 10(三星框架)上尝试了我提供的代码,默认音量条不可见。因此,我也在我的 S4 运行 LineageOS 10 上尝试了它,结果相同。没有出现音量条。

关于 adjustStreamVolume or adjustVolume 它们都允许您更改音量频道,但 adjustStreamVolume 允许您更改特定频道,例如媒体、通话等。在我的示例中,它仅编辑媒体。

在应用程序级别是你可以做任何事情,因为每个动作都有一个事件,你可以根据你自己的选择创建自己的动作 UI您的选择,例如隐藏 STOCK VOLUME DIALOG 并显示 CUSTOM DIALOG,但 在 OS 等级没有 你不能。

Reason

Android Framework and any other architectural Component work on the basics of events, like in Android OS if you do something, an event is initialized and a broadcast is sent to all the framework and it can be read by any application having right PERMISSIONS and IDS for those Broadcasts, by using BROADCAST RECEIVERS and SERVICES in case of Notifications for special broadcasts.

How can you achieve your goals

I will not tell you every function and method for what you want to do but will tell you the recipe for achieving it, with the help of Andoird's Official DOCs and with great people at Whosebug

对于所有的事件你都可以使用这个覆盖方法

 @Override
public boolean onKey**`YourKeyEvent`**(int keyCode, KeyEvent event) {
    switch (event.getKeyCode()) {
        case KeyEvent.Your_Event_One:
            //your actions (perform code on some keyEvent)

            break;

        case KeyEvent.Your_Event_Two:
           //your actions (perform code on some keyEvent)

        break;
    }
}

以上代码适用于大多数事件,但对于某些事件,您还需要 Broadcast Reciever

LIST OF KEY_EVENTS (Android's Docs)

List Of Key Codes (Android's Code)

编辑 对于音量变化,请查看 This post,通过使用此 post,您可以创建音量摇杆动作的回调,然后隐藏股票对话框,并使用主屏幕上的服务显示您自己的对话框。

注意:我过去从未接触过隐藏库存 UI 组件,所以我不确定那部分。