Android系统服务

概述

本篇博文主要介绍的是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的服务对象

TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);

示例

调用拨号器拨打电话号码

Uri uri=Uri.parse("tel:"+电话号码);
Intent intent=new Intent(Intent.ACTION_DIAL,uri);
startActivity(intent);  

获取Sim卡信息与网络信息

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,记得清单文件添加权限

<!-- 添加访问手机位置的权限 -->
<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(独立信号单元)

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这个类

This class was deprecated in API level 4.
Replaced by android.telephony.SmsManager that supports both GSM and CDMA.

建议使用 android.telephony.SmsManager

SmsManager

调用系统发送短信功能

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

核心代码

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);
    }
}    

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

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

uses-permission android:name="android.permission.SEND_SMS"/>

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

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”)

核心代码

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:

//处理返回的发送状态
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:

//处理返回的接收状态
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对象实例

AudioManager audiomanage = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

常用方法

示例

简单的示例:使用Mediaplayer播放音乐,通过AudioManager调节音量大小与静音!

对了,先在res下创建一个raw的文件夹,往里面丢一个MP3资源文件!

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

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

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

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

    <Button
        android:id="@+id/btn_lower"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="调低音量" />

    <Button
        android:id="@+id/btn_quite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="静音" />

</LinearLayout> 
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实例:

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中添加下述权限: <uses-permission android:name="android.permission.VIBRATE"/>

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

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

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

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

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

    <Button
        android:id="@+id/btn_rhythm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="节奏振动" />

    <Button
        android:id="@+id/btn_cancle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="取消振动" />
</LinearLayout>
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();
        }
    }
}

清单文件权限

<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的布局!

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_set"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="设置闹钟" />

    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="关闭闹钟"
        android:visibility="gone" />

</LinearLayout>
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

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

时间: 2024-10-06 00:10:57

Android系统服务的相关文章

Android 系统服务一览表

在<Zygote进程[3]--SystemServer的诞生>一文中介绍了SystemServer的诞生,本文来看一下SystemServer中初始化的系统服务. 1.AccountManagerService Android账户服务,提供了对账户.密码.授权的集中管理. 2.AccessibilityManagerService 辅助管理程序截获所有的用户输入,并根据这些输入给用户一些额外的反馈,起到辅助的效果,View的点击.焦点等事件分发管理服. 3.ActivityManagerSer

Android 系统服务

Android系统服务大致分为三大类:本地守护进程.Native系统服务和Java系统服务.如下图所示: 本地守护进程 init进程根据init.rc文件中的定义,启动本地守护进程.这些进程会常驻在系统中,有的只会启动一次,有的如果退出了,还会被init启动.具体的启动方式就在init.rc中定义. 下面大体列举几个守护进程及其功能. 守护进程 功能 vold 管理存储设备,自动安装存储设备,将设备分区格式化 netd 管理蓝牙.wifi.usb等各种网络连接 installd 负责安装及卸载软

新建android系统服务

一.Android系统服务 Android提供了很多系统服务:如ActivityManger,PowerManger,WindowManger,WifiManger等等. 这些服务都是系统启动开始就一直常驻的,如果app需要使用相应的系统服务(如获取当前wifi的状态),则需要通过Binder去访问系统服务. 例如:WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 二.

Android系统服务-简介

http://blog.csdn.net/chenyafei617/article/details/6577907 Introduction 我们知道Android系统服务挺多的,做程序时经常会用到,要想把这么多的服务都了解透彻还真不是一两天就能搞定的,首先我们得又有一个框架,脑海里要形成这样的模型,android到底有哪些服务,针对这些服务分类去学习他们,今天发点时间把Android中的一些系统服务整理一下,大部分都是收集网络上的资料.自己也当作是一次学习机会,好了废话不多说了,请看下文: g

Android系统服务(SystemService)简介

什么是SystemService 我们在Android开发过程中经常会用到各种各样的系统管理服务,如进行窗口相关的操作会用到窗口管理服务WindowManager,进行电源相关的操作会用到电源管理服务PowerManager,还有很多其他的系统管理服务,如通知管理服务NotifacationManager.振动管理服务Vibrator.电池管理服务BatteryManager-- 这些Manager提供了很多对系统层的控制接口.对于App开发者,只需要了解这些接口的使用方式就可以方便的进行系统控

Android系统服务-WindowManager

WindowManager是Android中一个重要的服务(Service ).WindowManager Service 是全局的,是唯一的.它将用户的操作,翻译成为指令,发送给呈现在界面上的各个Window.Activity会将顶级的控件注册到 Window Manager 中,当用户真是触碰屏幕或键盘的时候,Window Manager就会通知到,而当控件有一些请求产生,也会经由ViewParent送回到Window Manager中.从而完成整个通信流程.整个Android的窗口机制是基

Android提供的系统服务之--AlarmManager(闹钟服务)

Android提供的系统服务之--AlarmManager(闹钟服务) --转载请注明出处:coder-pig 本节引言: 本节主要介绍的是Android系统服务中的---AlarmManager(闹钟服务), 除了开发手机闹钟外,更多的时候是作为一个全局的定时器,通常与Service 结合,在特定时间启动其他的组件!本节就来对这个AlarmManager来进行解析 同时通过小闹钟与自动换壁纸来演示这个AlarmManager的用法,好了,开始本节的 内容吧! 本节正文: 1.概念与相关属性方法

Android提供的系统服务之--WindowManager(窗口管理服务)

Android提供的系统服务之--WindowManager(窗口管理服务) --转载请注明出处:coder-pig 本节引言: 本节我们来探讨下这个Android系统服务中的WindowManager(窗口管理服务), 他是显示View的最底层,好像我们的Actviity和Dialog,以及Toast的底层实现都用到 这个WindowManager,他是全局的!核心其实就是WindowManager调用addView, removeView,updateViewLayout这几个方法来显示Vi

Android提供的系统服务之--LayoutInflater(布局服务)

Android提供的系统服务之--LayoutInflater(布局服务) --转载请注明出处:coder-pig 本节引言: 本节我们只要是介绍Android系统服务中的--LayoutInflater(布局服务), 相信大家已经习惯了通过Activity.setContentView( )方法来我们的布局文件, 底层的底层还是通过这个系统的LayoutInflater来完成的! 工作原理就是使用Android内置的pull解析器来解析布局~ 而在前几天写的blog中用到的动态布局,就是用到这