Android系统服务

2021-08-16 10:26:55 浏览数 (1)

概述

本篇博文主要介绍的是Android中的Java服务。 这部分服务大部分都有一个Manager类,其实就是一个RPC调用,用户通过调用xxxManager的方法,实际上被Binder给迁移到system_server进程中对应的xxxManagerService中对应的方法,并将结果再通过binder带回。


常用的有如下几个:

PowerManagerService –> PowerManager

Tables

Are

PowerManagerService –> PowerManager

Android 的电源管理

ActivityManagerService->ActivityManager

整个Android framework框架中最为核心的一个服务,管理整个框架中任务、进程管理, Intent解析等的核心实现。虽然名为Activity的Manager Service,但它管辖的范围,不只是Activity,还有其他三大组件,和它们所在的进程。也就是说用户应用程序的生命管理,都是由他负责的。

TelephonyRegistry->TelephonyManager

电话注册、管理服务模块,可以获取电话的链接状态、信号强度等等

PackageManagerService -> PackageManager

包括对软件包的解包,验证,安装以及升级等等,对于我们现在不能安装.so文件的问题,应该先从这块着手分析原因。

AccountManagerService -> AccountManager

提供账户、密码和authtoken管理设备上的账户

ContentService -> ContentResolver

内容服务,主要是数据库等提供解决方法的服务。

BatteryService

监控电池充电及状态的服务,当状态改变时,会广播Intent

WindowManagerService -> WindowManager -> PhoneWindowManager

和ActivityManagerService高度粘合窗口管理,这里最核心的就是输入事件的分发和管理。

AlarmManagerService -> AlarmManager

闹钟服务程序

BluetoothService -> BluetoothDevice

蓝牙的后台管理和服务程序

ClipboardService -> ClipboardManager

和其他系统的clipBoard服务类似,提供复制黏贴功过。

InputMethodManagerService -> InputMethodManager

输入法的管理服务程序,包括何时使能输入法,切换输入法等等。

NetStatService

手机网络服务

ConnectivityService -> ConnectivityManager

网络连接状态服务,可供其他应用查询,当网络状态变化时,也可广播改变。

NotificationManagerService -> NotificationManager

负责管理和通知后台事件的发生等,这个和statusbar胶黏在一起,一般会在statusbar上添加响应图标。用户可以通过这知道系统后台发生了什么

WallpaperManagerService -> WallpaperManager

管理桌面背景的服务,深度定制化桌面系统

AppWidgetService -> AppWidgetManager

Android可以让用户写的程序以widget的方式放在桌面上,这就是这套管理和服务的接口

AudioService -> AudioManager

AudioFlinger的上层管理封装,主要是音量、音效、声道及铃声等的管理


TelephonyManager(电话管理器)

官方API

TelecomManager

获得TelephonyManager的服务对象

代码语言:javascript复制
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);

示例

调用拨号器拨打电话号码

代码语言:javascript复制
Uri uri=Uri.parse("tel:" 电话号码);    
Intent intent=new Intent(Intent.ACTION_DIAL,uri);    
startActivity(intent);  

获取Sim卡信息与网络信息

代码语言:javascript复制
public class MainActivity extends AppCompatActivity {

    private TextView tv_phone1;
    private TextView tv_phone2;
    private TextView tv_phone3;
    private TextView tv_phone4;
    private TextView tv_phone5;
    private TextView tv_phone6;
    private TextView tv_phone7;
    private TextView tv_phone8;
    private TextView tv_phone9;
    private TelephonyManager tManager;
    private String[] phoneType = {"未知","2G","3G","4G"};
    private String[] simState = {"状态未知","无SIM卡","被PIN加锁","被PUK加锁",
            "被NetWork PIN加锁","已准备好"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //①获得系统提供的TelphonyManager对象的实例
        tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        bindViews();
    }

    private void bindViews() {
        tv_phone1 = (TextView) findViewById(R.id.tv_phone1);
        tv_phone2 = (TextView) findViewById(R.id.tv_phone2);
        tv_phone3 = (TextView) findViewById(R.id.tv_phone3);
        tv_phone4 = (TextView) findViewById(R.id.tv_phone4);
        tv_phone5 = (TextView) findViewById(R.id.tv_phone5);
        tv_phone6 = (TextView) findViewById(R.id.tv_phone6);
        tv_phone7 = (TextView) findViewById(R.id.tv_phone7);
        tv_phone8 = (TextView) findViewById(R.id.tv_phone8);
        tv_phone9 = (TextView) findViewById(R.id.tv_phone9);

        tv_phone1.setText("设备编号:"   tManager.getDeviceId());
        tv_phone2.setText("软件版本:"   (tManager.getDeviceSoftwareVersion()!= null?
                tManager.getDeviceSoftwareVersion():"未知"));
        tv_phone3.setText("运营商代号:"   tManager.getNetworkOperator());
        tv_phone4.setText("运营商名称:"   tManager.getNetworkOperatorName());
        tv_phone5.setText("网络类型:"   phoneType[tManager.getPhoneType()]);
        tv_phone6.setText("设备当前位置:"   (tManager.getCellLocation() != null ? tManager
                .getCellLocation().toString() : "未知位置"));
        tv_phone7.setText("SIM卡的国别:"   tManager.getSimCountryIso());
        tv_phone8.setText("SIM卡序列号:"   tManager.getSimSerialNumber());
        tv_phone9.setText("SIM卡状态:"   simState[tManager.getSimState()]);
    }
}

访问以上API,记得清单文件添加权限

代码语言:javascript复制
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

获取手机的信号强度

网络信号强度的单位是dBm(毫瓦分贝),一般用负数表示,正常手机信号变化范围是从-110dBm (差)到-50dBm(好)之间,如果你比-50dBm还小的话,说明你就站在基站的附近。

另外2G,3G,4G获得信号强度的方式都是重写PhoneStateListener的onSignalStrengthsChanged() 方法,当信号强度发生改变的时候就会触发这个事件,我们可以在这个事件里获取信号强度!

手机获取信号强度代码示例: dBm =-113 2*asu这是一个固定公式,asu(独立信号单元)

代码语言:javascript复制
public class MainActivity extends AppCompatActivity {

    private TextView tv_rssi;
    private MyPhoneStateListener mpsListener;
    private TelephonyManager tManager;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tManager = ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE));
        tv_rssi = (TextView) findViewById(R.id.tv_rssi);
        mpsListener  = new MyPhoneStateListener();
        tManager.listen(mpsListener,290);
    }

    private class MyPhoneStateListener extends PhoneStateListener {
        private int asu = 0,lastSignal = 0;
        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            asu = signalStrength.getGsmSignalStrength();
            lastSignal = -113   2 * asu;
            tv_rssi.setText("当前手机的信号强度:"   lastSignal   " dBm" );
            super.onSignalStrengthsChanged(signalStrength);
        }
    }
}

getEvdoDbm():电信3G getCdmaDbm():联通3G getLteDbm():4G

监听手机的所有来电

详见本人另外一篇博客来去电拦截

黑名单来电自动挂断

详见本人另外一篇博客AIDL与来去电自动挂断


SmsManager(短信管理器)

官方API

不建议使用 android.telephony.gsm.SmsManager这个类

代码语言:javascript复制
This class was deprecated in API level 4.
Replaced by android.telephony.SmsManager that supports both GSM and CDMA.

建议使用 android.telephony.SmsManager

SmsManager

调用系统发送短信功能

这样发短信,app安装的时候就可以少写一条发短信的权限

核心代码

代码语言:javascript复制
public void SendSMSTo(String phoneNumber,String message){    
    //判断输入的phoneNumber是否为合法电话号码  
    if(PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber)){  
        //Uri.parse("smsto") 这里是转换为指定Uri,固定写法  
        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" phoneNumber));        
        intent.putExtra("sms_body", message);              
        startActivity(intent);    
    }    
}    

调用系统提供的短信接口发送短信

这个就需要发短信的权限啦

代码语言:javascript复制
uses-permission android:name="android.permission.SEND_SMS"/>

我们直接调用SmsManager为我们提供的短信接口发送短信:

代码语言:javascript复制
sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliverIntent);

参数依次是:

  • destinationAddress:收信人的电话号码
  • scAddress:短信中心的号码,null的话使用当前默认的短信服务中心
  • text:短信内容
  • sentIntent:短信发送状态的信息:(发送状态的Intent) 如果不为null,当消息成功发送或失败这个PendingIntent就广播。结果代码是Activity.RESULT_OK 表示成功,或RESULT_ERROR_GENERIC_FAILURE、RESULT_ERROR_RADIO_OFF、RESULT_ERROR_NULL_PDU 之一表示错误。对应RESULT_ERROR_GENERIC_FAILURE,sentIntent可能包括额外的”错误代码”包含一 个无线电广播技术特定的值,通常只在修复故障时有用。每一个基于SMS的应用程序控制检测sentIntent。 如果sentIntent是空,调用者将检测所有未知的应用程序,这将导致在检测的时候发送较小数量的SMS。
  • deliverIntent:短信是否被对方收到的状态信息:(接收状态的Intent) 如果不为null,当这个短信发送到接收者那里,这个PendtingIntent会被广播, 状态报告生成的pdu(指对等层次之间传递的数据单位)会拓展到数据(”pdu”)

核心代码

代码语言:javascript复制
public void sendSMS(String phoneNumber,String message){  
    //获取短信管理器   
    android.telephony.SmsManager smsManager = android.telephony.SmsManager.getDefault();  
    //拆分短信内容(手机短信长度限制),貌似长度限制为140个字符,就是
    //只能发送70个汉字,多了要拆分成多条短信发送
    //第四五个参数,如果没有需要监听发送状态与接收状态的话可以写null    
    List<String> divideContents = smsManager.divideMessage(message);   
    for (String text : divideContents) {    
        smsManager.sendTextMessage(phoneNumber, null, text, sentPI, deliverPI);    
    }  
} 

可能你还需要监听短信是否发送成功,或者收信人是否接收到信息,就把下面的加上吧:

处理返回发送状态的sentIntent:

代码语言:javascript复制
//处理返回的发送状态   
String SENT_SMS_ACTION = "SENT_SMS_ACTION";  
Intent sentIntent = new Intent(SENT_SMS_ACTION);  
PendingIntent sentPI = PendingIntent.getBroadcast(context, 0, sentIntent,  0);  
//注册发送信息的广播接收者
context.registerReceiver(new BroadcastReceiver() {  
    @Override  
    public void onReceive(Context _context, Intent _intent) {  
        switch (getResultCode()) {  
        case Activity.RESULT_OK:
            Toast.makeText(context, "短信发送成功", Toast.LENGTH_SHORT).show();  
            break;  
        case SmsManager.RESULT_ERROR_GENERIC_FAILURE:    //普通错误
            break;
        case SmsManager.RESULT_ERROR_RADIO_OFF:         //无线广播被明确地关闭
            break;          
        case SmsManager.RESULT_ERROR_NULL_PDU:          //没有提供pdu
            break;      
        case SmsManager.RESULT_ERROR_NO_SERVICE:         //服务当前不可用
            break;              
        }  
    }  
}, new IntentFilter(SENT_SMS_ACTION)); 

处理返回接收状态的deliverIntent:

代码语言:javascript复制
//处理返回的接收状态   
String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";  
//创建接收返回的接收状态的Intent  
Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION);  
PendingIntent deliverPI = PendingIntent.getBroadcast(context, 0,deliverIntent, 0);  
context.registerReceiver(new BroadcastReceiver() {  
   @Override  
   public void onReceive(Context _context, Intent _intent) {  
       Toast.makeText(context,"收信人已经成功接收", Toast.LENGTH_SHORT).show();  
   }  
}, new IntentFilter(DELIVERED_SMS_ACTION)); 

AudioManager(音频管理器)

官方API

AudioManager

获得AudioManager对象实例

代码语言:javascript复制
AudioManager audiomanage = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

常用方法

示例

简单的示例:使用Mediaplayer播放音乐,通过AudioManager调节音量大小与静音! 对了,先在res下创建一个raw的文件夹,往里面丢一个MP3资源文件!

代码语言:javascript复制
"http://schemas.android.com/apk/res/android"
    android:id="@ id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    id="@ id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="播放" />

    id="@ id/btn_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:enabled="false"
        android:text="停止" />

    id="@ id/btn_higher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="调高音量" />

    id="@ id/btn_lower"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="调低音量" />
代码语言:javascript复制
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_start;
    private Button btn_stop;
    private Button btn_higher;
    private Button btn_lower;
    private Button btn_quite;
    private MediaPlayer mePlayer;
    private AudioManager aManager;
    //定义一个标志用来标示是否点击了静音按钮
    private int flag = 1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获得系统的音频对象
        aManager = (AudioManager) getSystemService(Service.AUDIO_SERVICE);
        //初始化mediaplayer对象,这里播放的是raw文件中的mp3资源
        mePlayer = MediaPlayer.create(MainActivity.this, R.raw.countingstars);
        //设置循环播放:
        mePlayer.setLooping(true);
        bindViews();
    }

    private void bindViews() {
        btn_start = (Button) findViewById(R.id.btn_start);
        btn_stop = (Button) findViewById(R.id.btn_stop);
        btn_higher = (Button) findViewById(R.id.btn_higher);
        btn_lower = (Button) findViewById(R.id.btn_lower);
        btn_quite = (Button) findViewById(R.id.btn_quite);

        btn_start.setOnClickListener(this);
        btn_stop.setOnClickListener(this);
        btn_higher.setOnClickListener(this);
        btn_lower.setOnClickListener(this);
        btn_quite.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_start:
                btn_stop.setEnabled(true);
                mePlayer.start();
                btn_start.setEnabled(false);
                break;
            case R.id.btn_stop:
                btn_start.setEnabled(true);
                mePlayer.pause();
                btn_stop.setEnabled(false);
                break;
            case R.id.btn_higher:
                // 指定调节音乐的音频,增大音量,而且显示音量图形示意
                aManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
                        AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
                break;
            case R.id.btn_lower:
                // 指定调节音乐的音频,降低音量,只有声音,不显示图形条
                aManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
                        AudioManager.ADJUST_LOWER, AudioManager.FLAG_PLAY_SOUND);
                break;
            case R.id.btn_quite:
                // 指定调节音乐的音频,根据isChecked确定是否需要静音
                flag *= -1;
                if (flag == -1) {
                    aManager.setStreamMute(AudioManager.STREAM_MUSIC, true);   //API 23过期- -
//                    aManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE,
//                            AudioManager.FLAG_SHOW_UI);   //23以后的版本用这个
                    btn_quite.setText("取消静音");
                } else {
                    aManager.setStreamMute(AudioManager.STREAM_MUSIC, false);//API 23过期- -
//                    aManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_UNMUTE,
//                            AudioManager.FLAG_SHOW_UI);  //23以后的版本用这个
                    aManager.setMicrophoneMute(false);
                    btn_quite.setText("静音");
                }
                break;
        }
    }
}

设置静音的方法setStreamMute()在API 23版本过期, 可以使用另一个方法adjustStreamVolume(int, int, int),然后第三个属性设置: ADJUST_MUTE 或 ADJUST_UNMUTE! 对了,还有: 如果adjustStreamVolume()的第三个参数你设置了振动(Vibrator), 需要在AndroidManifest.xml中添加这个权限!

<uses-permission android:name=”android.permission.VIBRATE”/>


Vibrator(振动器)

官方API

Vibrator

获得Vibrator实例:

代码语言:javascript复制
Vibrator vb = (Vibrator)getSystemService(Service.VIBRATOR_SERVICE);

相关方法:

  • abstract void cancel():关闭或者停止振动器
  • abstract boolean hasVibrator():判断硬件是否有振动器
  • void vibrate(long milliseconds):控制手机振动为milliseconds毫秒
  • void vibrate(long[] pattern,int repeat):指定手机以pattern指定的模式振动! 比如:pattern为new int[200,400,600,800],就是让他在200,400,600,800这个时间交替启动与关闭振动器! 而第二个则是重复次数,如果是-1的只振动一次,如果是0的话则一直振动 还有其他两个方法用得不多~ 对了,使用振动器还需要在AndroidManifest.xml中添加下述权限:

示例:设置频率不同的震动器

对于Vibrator用的最广泛的莫过于所谓的手机按摩器类的app

代码语言:javascript复制
"http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    id="@ id/btn_hasVibrator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="判断是否有振动器" />


    id="@ id/btn_short"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="短振动" />

    id="@ id/btn_long"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="长振动" />

    id="@ id/btn_rhythm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="节奏振动" />
代码语言:javascript复制
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_hasVibrator;
    private Button btn_short;
    private Button btn_long;
    private Button btn_rhythm;
    private Button btn_cancle;
    private Vibrator myVibrator;
    private Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获得系统的Vibrator实例:
        myVibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);
        mContext = MainActivity.this;
        bindViews();
    }

    private void bindViews() {
        btn_hasVibrator = (Button) findViewById(R.id.btn_hasVibrator);
        btn_short = (Button) findViewById(R.id.btn_short);
        btn_long = (Button) findViewById(R.id.btn_long);
        btn_rhythm = (Button) findViewById(R.id.btn_rhythm);
        btn_cancle = (Button) findViewById(R.id.btn_cancle);

        btn_hasVibrator.setOnClickListener(this);
        btn_short.setOnClickListener(this);
        btn_long.setOnClickListener(this);
        btn_rhythm.setOnClickListener(this);
        btn_cancle.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_hasVibrator:
                Toast.makeText(mContext, myVibrator.hasVibrator() ? "当前设备有振动器" : "当前设备无振动器",
                        Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_short:
                myVibrator.cancel();
                myVibrator.vibrate(new long[]{100, 200, 100, 200}, 0);
                Toast.makeText(mContext, "短振动", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_long:
                myVibrator.cancel();
                myVibrator.vibrate(new long[]{100, 100, 100, 1000}, 0);
                Toast.makeText(mContext, "长振动", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_rhythm:
                myVibrator.cancel();
                myVibrator.vibrate(new long[]{500, 100, 500, 100, 500, 100}, 0);
                Toast.makeText(mContext, "节奏振动", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_cancle:
                myVibrator.cancel();
                Toast.makeText(mContext, "取消振动", Toast.LENGTH_SHORT).show();
        }
    }
}

清单文件权限

代码语言:javascript复制
<uses-permission android:name="android.permission.VIBRATE"/>

AlarmManager(闹钟服务)

官方API

AlarmManager

相关方法

关键参数说明:

示例:一个简单的定时任务

要说的是,此例子只在Android 4.4以下的系统可行,5.0以上并不可行,后续如果有5.0 以上AlarmManager的解决方案,到时再补上!另外,这里用set方法可能有点不准,如果要 更精确的话可以使用setExtra()方法来设置AlarmManager!

首先一个简单的布局文件:activity_main.xml,另外在res创建一个raw文件夹,把音频文件丢进去! 另外创建一个只有外层布局的activity_clock.xml作为闹钟响时Activity的布局!

代码语言:javascript复制
"http://schemas.android.com/apk/res/android"
    android:id="@ id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    id="@ id/btn_set"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置闹钟" />
代码语言:javascript复制
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button btn_set;
    private Button btn_cancel;
    private AlarmManager alarmManager;
    private PendingIntent pi;

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

    private void bindViews() {
        btn_set = (Button) findViewById(R.id.btn_set);
        btn_cancel = (Button) findViewById(R.id.btn_cancel);
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

        Intent intent = new Intent(MainActivity.this, ClockActivity.class);
        pi = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);

        btn_set.setOnClickListener(this);
        btn_cancel.setOnClickListener(this);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_set:
                Calendar currentTime = Calendar.getInstance();
                new TimePickerDialog(MainActivity.this, 0,
                        new TimePickerDialog.OnTimeSetListener() {
                            @Override
                            public void onTimeSet(TimePicker view,
                                                  int hourOfDay, int minute) {
                                //设置当前时间
                                Calendar c = Calendar.getInstance();
                                c.setTimeInMillis(System.currentTimeMillis());
                                // 根据用户选择的时间来设置Calendar对象
                                c.set(Calendar.HOUR, hourOfDay);
                                c.set(Calendar.MINUTE, minute);
                                // ②设置AlarmManager在Calendar对应的时间启动Activity
                                alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);
                                Log.e("HEHE",c.getTimeInMillis() "");   //这里的时间是一个unix时间戳
                                // 提示闹钟设置完毕:
                                Toast.makeText(MainActivity.this, "闹钟设置完毕~"  c.getTimeInMillis(),
                                        Toast.LENGTH_SHORT).show();
                            }
                        }, currentTime.get(Calendar.HOUR_OF_DAY), currentTime
                        .get(Calendar.MINUTE), false).show();
                btn_cancel.setVisibility(View.VISIBLE);
                break;
            case R.id.btn_cancel:
                alarmManager.cancel(pi);
                btn_cancel.setVisibility(View.GONE);
                Toast.makeText(MainActivity.this, "闹钟已取消", Toast.LENGTH_SHORT)
                        .show();
                break;
        }
    }
}

闹铃页面的ClockActivity.java

代码语言:javascript复制
public class ClockActivity extends AppCompatActivity {

    private MediaPlayer mediaPlayer;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_clock);
        mediaPlayer = mediaPlayer.create(this,R.raw.pig);
        mediaPlayer.start();
        //创建一个闹钟提醒的对话框,点击确定关闭铃声与页面
        new AlertDialog.Builder(ClockActivity.this).setTitle("闹钟").setMessage("小猪小猪快起床~")
                .setPositiveButton("关闭闹铃", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mediaPlayer.stop();
                        ClockActivity.this.finish();
                    }
                }).show();
    }
}

核心流程

  • AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 获得系统提供的AlarmManager服务的对象
  • Intent设置要启动的组件: Intent intent = new Intent(MainActivity.this, ClockActivity.class);
  • PendingIntent对象设置动作,启动的是Activity还是Service,又或者是广播! PendingIntent pi = =PendingIntent.getActivity(MainActivity.this, 0, intent, 0);
  • 调用AlarmManager的set( )方法设置单次闹钟的闹钟类型,启动时间以及PendingIntent对象! alarmManager.set(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(), pi);

另外假如出现闹铃无效的话,你可以从这些方面入手:

1.系统版本或者手机,5.0以上基本没戏,小米,自行百度吧~ 2.ClockActivity有注册没? 3.假如你用的是alarmManager发送广播,广播再激活Activity的话,则需要为Intent设置一个flag: i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 4. PendingIntent,要写成getActivity启动闹铃页面


PowerManager(电源服务)

powermanager

WindowManager(窗口管理服务)

windowmanager

LayoutInflater(布局服务)

layoutinflater

WallpaperManager(壁纸管理器)

wallpapermanager

0 人点赞