目录

  • 系统服务
  • 系统服务样例
  • 程序需求
  • 功能设计
  • 代码编写
  • AdjustVolumeDialog.java
  • Diglog.xml
  • MainActivity
  • Activity_main.xml
  • 运行效果
  • 参考资料

系统服务

用户编写的 Service 是后台应用服务程序,位于 Android 系统应用层。相对而言的系统服务(System Services)可以看作 Android 系统的内置软件,它是 Android 操作系统 Java 应用程序下层的,伴随操作系统启动而运行的系统后台服务程序。系统服务是 Android 系统运行的基石,它配合 binder、Dalvik 虚拟机和 Android 应用程序构成了一个多进程交互通信、交互服务的 Android 系统。
Android 的所有服务循环都建立在 System Server 之上,Service manager 是管理系统服务的进程,通过 ServerManager 的 add_service() 方法把服务加入到服务列表中,实现对服务的管理。Activity 中有一个重要的方法 getSystemService(),根据传入的 Name 来取得对应的 Object,然后转换成相应的服务对象。

public Object getSystemService(String name);

以下是常用的系统服务:

系统服务名

返回的对象

说明

WINDOW_SERVICE

WindowManager

管理打开的窗口程序

LAYOUT_INFLATER_SERVICE

LayoutInflater

取得 xml 里定义的 View

ACTIVITY_SERVICE

ActivityManager

管理应用程序的系统状态

POWER_SERVICE

PowerManger

电源服务

ALARM_SERVICE

AlarmManager

闹钟服务

NOTIFICATION_SERVICE

NotificationManager

状态栏服务

KEYGUARD_SERVICE

KeyguardManager

键盘锁服务

LOCATION_SERVICE

LocationManager

位置服务,如 GPS

SEARCH_SERVICE

SearchManager

搜索服务

VIBRATOR SERVICE

Vibrator手

机振动服务

CONNECTIVITY_SERVICE

Connectivity

网络连接服务

WIFI_SERVICE

WifiManager

WiFi 服务

TELEPHONY_SERVICE

TeleponyManager

电话服务

系统服务样例

程序需求

利用 Android APP 的系统服务,获取并设置系统音量。

功能设计

首先需要获取不同音量的最大值,保值音量的设置是正确的不会越界,接着再获取当前的音量作为拖动条的初始值。接着就是当用户点击“ok”的时候,根据拖动条的值使用 set 方法来设置系统音量。

代码编写

AdjustVolumeDialog.java

package com.example.yinlian;

import android.app.AlertDialog;
import android.content.Context;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.NonNull;

public class AdjustVolumeDialog extends AlertDialog {

    private AudioManager audioManager;
    private SeekBar seekbar1, seekbar2, seekbar3;
    private int screenWidth;
    private TextView textView1,textView2,textView3;
    private CheckBox ch;
    private Button ok, cancel;
    private Context context;

    protected AdjustVolumeDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
    }

    /**
     * 在onCreate方法里面 setContentView() 否则dialog的自定义view 显示不出来
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        screenWidth = dm.widthPixels;         // 屏幕宽度(像素)
        initView();
    }

    /**
     * 自定义dialog 的view
     * 设置 位置
     */
    private void initView() {
        View root = LayoutInflater.from(getContext()).inflate(R.layout.dialog, null);
        setContentView(root);
        seekbar1 = root.findViewById(R.id.ringseekBar);
        seekbar2 = root.findViewById(R.id.mediaseekBar);
        seekbar3 = root.findViewById(R.id.alarmseekBar);
        textView1 = (TextView) findViewById(R.id.ring);
        textView2 = (TextView) findViewById(R.id.media);
        textView3 = (TextView) findViewById(R.id.Alarm);
        ch = (CheckBox)findViewById(R.id.choose);
        ok     = (Button)findViewById(R.id.ok);
        cancel = (Button)findViewById(R.id.cancel);

        seekbar1.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_RING));
        seekbar2.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
        seekbar3.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM));
        int ringVolume   = audioManager.getStreamVolume(AudioManager.STREAM_RING);
        int musicVolume  = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        int alarmVolume  = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
        seekbar1.setProgress(ringVolume);
        seekbar2.setProgress(musicVolume);
        seekbar3.setProgress(alarmVolume);
        textView1.setText("铃声音量为:" + ringVolume);
        textView2.setText("媒体音量为:" + musicVolume);
        textView3.setText("闹钟音量为:" + alarmVolume);

        /* 设置SeekBar 监听setOnSeekBarChangeListener */
        seekbar1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            /*拖动条停止拖动时调用 */
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
            /*拖动条开始拖动时调用*/
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
            /* 拖动条进度改变时调用*/
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                textView1.setText("铃声音量为:" + progress);
            }
        });

        seekbar2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                textView2.setText("媒体音量为:" + progress);
            }
        });

        seekbar3.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                textView3.setText("闹钟音量为:" + progress);
            }
        });

        ok.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                int ringVolume = seekbar1.getProgress();
                if(ch.isChecked()) {
                    audioManager.setStreamVolume(AudioManager.STREAM_RING, seekbar1.getProgress(), AudioManager.FLAG_PLAY_SOUND);
                    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, seekbar1.getProgress(), AudioManager.FLAG_PLAY_SOUND);
                    seekbar2.setProgress(ringVolume);
                    textView2.setText("媒体音量为:" + ringVolume);
                    audioManager.setStreamVolume(AudioManager.STREAM_ALARM, seekbar1.getProgress(), AudioManager.FLAG_PLAY_SOUND);
                    seekbar3.setProgress(ringVolume);
                    textView3.setText("闹钟音量为:" + ringVolume);
                }
                else {
                    audioManager.setStreamVolume(AudioManager.STREAM_RING, seekbar1.getProgress(), AudioManager.FLAG_PLAY_SOUND);
                    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, seekbar2.getProgress(), AudioManager.FLAG_PLAY_SOUND);
                    audioManager.setStreamVolume(AudioManager.STREAM_ALARM, seekbar3.getProgress(), AudioManager.FLAG_PLAY_SOUND);
                }
            }
        });

        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dismiss();
            }
        });

        // 设置dialog中view的位置
        Window window = getWindow();
        WindowManager.LayoutParams lp = window.getAttributes();
        lp.gravity = Gravity.CENTER;    //居中
        window.setAttributes(lp);
    }

    /**
     * dialog显示时回调
     * 广播注册
     */
    @Override
    public void show() {
        super.show();
        IntentFilter filter = new IntentFilter() ;
        filter.addAction("android.media.VOLUME_CHANGED_ACTION") ;
    }

    /**
     * dialog消失时回调
     * 广播反注册
     */
    @Override
    public void dismiss() {
        super.dismiss();
    }
}

Diglog.xml

接着就设置一个弹窗来实现这个功能即可。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parentLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/seekLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/volume"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="Volume"
            android:textSize="40dp"></TextView>

        <TextView
            android:id="@+id/ring"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="Ringtone"
            android:textSize="20dp">
        </TextView>

        <SeekBar
            android:id="@+id/ringseekBar"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:maxHeight="20dp"
            android:paddingStart="15dp"
            android:paddingEnd="15dp"
            android:progressDrawable="@drawable/po_seekbar"
            android:thumb="@drawable/seekbar_thumb" />

        <TextView
            android:id="@+id/media"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="Media"
            android:textSize="20dp"></TextView>

        <SeekBar
            android:id="@+id/mediaseekBar"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:maxHeight="20dp"
            android:paddingStart="15dp"
            android:paddingEnd="15dp"
            android:progressDrawable="@drawable/po_seekbar"
            android:thumb="@drawable/seekbar_thumb" />

        <TextView
            android:id="@+id/Alarm"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="Alarm"
            android:textSize="20dp"></TextView>

        <SeekBar
            android:id="@+id/alarmseekBar"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:maxHeight="20dp"
            android:paddingStart="15dp"
            android:paddingEnd="15dp"
            android:progressDrawable="@drawable/po_seekbar"
            android:thumb="@drawable/seekbar_thumb" />

        <CheckBox
            android:id="@+id/choose"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="使用来电铃音音量进行通知"></CheckBox>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/ok"
                android:layout_width="114.0dip"
                android:layout_height="40.0dip"
                android:gravity="center"
                android:text="ok" />

            <Button
                android:id="@+id/cancel"
                android:layout_width="114.0dip"
                android:layout_height="40.0dip"
                android:layout_marginLeft="20.0dip"
                android:gravity="center"
                android:text="cancel" />

        </LinearLayout>
    </LinearLayout>
</LinearLayout>

MainActivity

package com.example.yinlian;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    Button btn;
    AdjustVolumeDialog adjustVolumeDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 需要为 dialog 设置一个 style
        adjustVolumeDialog = new AdjustVolumeDialog(this, R.style.Theme_Yinlian);
        btn = findViewById(R.id.btn);
        // 点击按钮弹出对话框
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                adjustVolumeDialog.show();
            }
        });
    }

    @Override
    protected void onDestroy() {
        if(adjustVolumeDialog!=null && adjustVolumeDialog.isShowing()) {
            adjustVolumeDialog.dismiss();
        }
        super.onDestroy();
    }
}

Activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.yinlian.MainActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="音量调节"
        android:layout_marginTop="50dp"
        android:layout_gravity="center"
        android:textSize="20dp"/>

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_gravity="center"
        android:textSize="20dp"
        android:text="调节">
    </Button>

</LinearLayout>

运行效果

打开弹窗。

android service 阻塞ui android system service_android


设置新的音量。

android service 阻塞ui android system service_android_02


使用来电音量来设置,媒体音量和闹钟音量会设置为来电音量。

android service 阻塞ui android system service_android_03