用户编写的 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 方法来设置系统音量。
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(); } }
接着就设置一个弹窗来实现这个功能即可。
<?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>
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(); } }
<?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 移动应用开发》,杨谊 主编、喻德旷 副主编,人民邮电出版社