1.创建、配置和启动Services
1创建Service文件 FirstService,需要继承Service
public class FirstService extends Service {
public FirstService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
Log.d("nc", "onCreate: ===================");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("nc", "onStartCommand: started");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("nc", "onDestroy: destoried");
}
}
2、在manifest上注册services
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fengray.myex016services">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".FirstService"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
3、activity文件中开启、关闭Service(通过intent来实现)
public class MainActivity extends AppCompatActivity {
private Button start,destory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Intent intent=new Intent(this,FirstService.class);
start=findViewById(R.id.start);
destory=findViewById(R.id.destory);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(intent);
}
});
destory.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopService(intent);
}
});
}
}
2.绑定本地Service并与之通信Services
1、创建BindService类,继承自Service类
public class BindService extends Service {
private int count;
private boolean quit;
private MyBinder binder=new MyBinder();
public BindService() {
}
class MyBinder extends Binder{
//获取Service的运行状态,即他的count
public int getCount(){
return BindService.this.count;
}
}
//Service被绑定时回调该方法
public IBinder onBind(Intent intent){
Log.d("nc", "onBind: Service is Binded");
return binder;
}
//Service被创建时回调该方法
@Override
public void onCreate() {
super.onCreate();
Log.d("nc", "onCreate: Service is created");
//启动一条线程,动态修改count状态值
new Thread(new Runnable(){
@Override
public void run() {
while (!quit){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
BindService.this.count++;
}
}
}).start();
}
//Service被断开连接时回调该方法
public boolean onUnbind(Intent intent){
Log.d("nc", "onUnbind: Service is Unbinded");
return true;
}
//Service被关闭之前回调该方法
public void onDestroy(){
super.onDestroy();
this.quit=true;
Log.d("nc", "onDestroy: Service is destroied");
}
}
2、主布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/start"
android:text="start"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/stop"
android:text="stop"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/getService"
android:text="getService"/>
</LinearLayout>
3、activity文件
public class MainActivity extends AppCompatActivity {
private Button btnbinder,btnunbind,btnget;
//保持所启动的Service的IBinder对象?啥叫保持,
private BindService.MyBinder binder;
//定义一个ServiceConnect对象
private ServiceConnection serviceConnection = new ServiceConnection() {
//当该activity与Service连接成功时回调该方法
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.d("nc", "onServiceConnected");
//获取Service的onBind方法所返回的MyBinder对象
binder=(BindService.MyBinder)iBinder;
}
//当该activity与Service断开连接时回调该方法
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d("nc", "onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnbinder=findViewById(R.id.start);
btnunbind=findViewById(R.id.stop);
btnget=findViewById(R.id.getService);
final Intent intent=new Intent(this,BindService.class);
btnbinder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//绑定制定service
//bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
//由于是获取context的bindSerVice方法可以显示地写为
getApplicationContext().bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
}
});
btnunbind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//unbindService(serviceConnection);
getApplicationContext().unbindService(serviceConnection);
}
});
btnget.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"Service的count值为:"+binder.getCount(),Toast.LENGTH_SHORT).show();
}
});
}
}
3.使用IntentService
1、IntenService文件
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
long endTime=System.currentTimeMillis()+5*1000;
Log.d("nc", "onStartCommand");
while (System.currentTimeMillis()<endTime){
synchronized (this){
try {
wait(endTime-System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Log.d("nc", "耗时任务完成================");
}
}
2、activity文件
public class MainActivity extends AppCompatActivity {
private Button startService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService=findViewById(R.id.btnIntentService);
final Intent intent=new Intent(this,MyIntentService.class);
startService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(intent);
}
});
}
}
4.跨进程调用Service(AIDL Service)
这里有一个参考文章:
4.电话管理器(TelephoyManager)
values目录里
<resources>
<!-- 声明一个名为statusNames的字符串数组 -->
<string-array name="statusNames">
<item>设备编号</item>
<item>软件版本</item>
<item>网络运营商代号</item>
<item>网络运营商名称</item>
<item>手机制式</item>
<item>蜂窝状态信息</item>
<item>SIM卡的国别</item>
<item>SIM卡序列号</item>
<item>SIM卡状态</item>
</string-array>
<!-- 声明一个名为simState的字符串数组 -->
<string-array name="simState">
<item>状态未知</item>
<item>无SIM卡</item>
<item>被PIN加锁</item>
<item>被PUK加锁</item>
<item>被NetWork PIN加锁</item>
<item>已准备好</item>
<item>未准备好</item>
<item>SIM损毁</item>
<item>读写SIM卡出错</item>
<item>SIM卡被限制使用</item>
</string-array>
<!-- 声明一个名为phoneType的字符串数组 -->
<string-array name="phoneType">
<item>未知</item>
<item>GSM</item>
<item>CDMA</item>
<item>SIP</item>
</string-array>
</resources>
2、list的布局页面
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/values"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
3、Manif
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fengray.myex019aidl">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
</manifest>
4、activity文件
public class MainActivity extends AppCompatActivity {
private ListView mylist;
private List<String> statusValues=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestPermissions(new String[] {Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.READ_PHONE_STATE},0x123);
setContentView(R.layout.activity_main);
mylist=findViewById(R.id.mylist);
}
@SuppressLint("MissingPermission")
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode==0x123 && grantResults[0]== PackageManager.PERMISSION_GRANTED && grantResults[1]==PackageManager.PERMISSION_GRANTED){
//获取系统的TelephoneyManager对象
TelephonyManager telephonyManager=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
//获取代表状态名称的数组
String [] statusNames=getResources().getStringArray(R.array.statusNames);
//获取代表SIM卡状态的数组
String [] simState=getResources().getStringArray(R.array.simState);
//获取代表电话网络类型的数组
String [] phoneType=getResources().getStringArray(R.array.phoneType);
//获取设备编号
statusValues.add(telephonyManager.getImei());
//获取系统平台的版本
statusValues.add(telephonyManager.getDeviceSoftwareVersion()!=null? telephonyManager.getDeviceSoftwareVersion():"未知");
//获取网络运营商代号
statusValues.add(telephonyManager.getNetworkOperator());
//获取网络运营商名称
statusValues.add(telephonyManager.getNetworkOperatorName());
//获取手机网路哦类型
statusValues.add(phoneType[telephonyManager.getPhoneType()]);
//获取蜂窝状态信息
statusValues.add(telephonyManager.getAllCellInfo()!=null? telephonyManager.getAllCellInfo().toString():"未知信息");
//获取sim卡国别
statusValues.add(telephonyManager.getSimCountryIso());
//获取sim序列号
statusValues.add(telephonyManager.getSimSerialNumber());
//获取sim卡状态
statusValues.add(simState[telephonyManager.getSimState()]);
//获取listView对象
List<Map<String,String>> status=new ArrayList<>();
//便利statusValues集合,将statusName,statuesValues数据封装到list集合中
for (int i=0;i<statusValues.size();i++){
Map<String,String> map = new HashMap<>();
map.put("name",statusNames[i]);
map.put("value",statusValues.get(i));
status.add(map);
}
//使用SimpleAdapter封装list数据
SimpleAdapter adapter=new SimpleAdapter(this,status,R.layout.line,new String[]{"name","value"},new int[]{R.id.name,R.id.values});
mylist.setAdapter(adapter);
}else {
Toast.makeText(this,"showinfo",Toast.LENGTH_SHORT).show();
}
}
}
最终效果
5.BroadcastReceive广播-发送与接收广播
1、创建FengRayReceiver类继承BroadcastReceiver
public class FengRayReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收到的intent的action为:"+intent.getAction()+"\n消息内容是:"+intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show();
}
}
2、在manifest文件中添加制定name为FengRayReceiver(BroadcastReceive的实现类),并制定接收到intent后的action为:com.fengray.myex020broadcast.action.FENGRAY_BROADCAST
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fengray.myex020broadcast">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".FengRayReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.fengray.myex020broadcast.action.FENGRAY_BROADCAST"/>
</intent-filter>
</receiver>
</application>
</manifest>
3、创建广播发送者,activity文件
public class MainActivity extends AppCompatActivity {
private Button sendBroadcast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendBroadcast=findViewById(R.id.sendBroadcast);
sendBroadcast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent();
intent.setAction("com.fengray.myex020broadcast.action.FENGRAY_BROADCAST");
intent.setPackage("com.fengray.myex020broadcast");
intent.putExtra("msg","今年网络授课");
sendBroadcast(intent);
}
});
}
}
6.有序广播
1、创建主activity文件,创建intent,并设置action,同时给intent加入消息,并发送有序广播
public class MainActivity extends AppCompatActivity {
private Button Mybut;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Mybut=findViewById(R.id.Mybut);
Mybut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent();
intent.setAction("com.fengray.myex021broadcast.action.MYACTION");
intent.setPackage("com.fengray.myex021broadcast");
intent.putExtra("msg","一则简单消息");
//发送有序广播
sendOrderedBroadcast(intent,null);
}
});
}
}
2、创建第一个接收器MyRecever1,并继承BroadcastReceiver
public class MyReceiver1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收到Intent的Action为:"+intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show();
//创建一个Bundle对象,并存入数据
Bundle bundle=new Bundle();
bundle.putString("first","第一个BroadCastReceiver存入的消息");
//将bundle放入结果中
setResultExtras(bundle);
//取消Broadcast
//abortBroadcast();
}
}
3、创建第一个接收器MyRecever2,并继承BroadcastReceiver
public class MyReceiver2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle=getResultExtras(true);
String first=bundle.getString("first");
Toast.makeText(context, "第一个存入的消息为:"+first, Toast.LENGTH_SHORT).show();
}
}
4、注册manifest文件,给不同的receiver指定不同的级别(priority)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fengray.myex021broadcast">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyReceiver1">
<intent-filter android:priority="20">
<action android:name="com.fengray.myex021broadcast.action.MYACTION"/>
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver2">
<intent-filter android:priority="0">
<action android:name="com.fengray.myex021broadcast.action.MYACTION"/>
</intent-filter>
</receiver>
</application>
</manifest>
7.基于Service的音乐播放器
assets资源文件在main上右键new-folder-assets folder
1、布局文件
public class MainActivity extends AppCompatActivity {
public static final String CTL_ACTION="com.fengray.action.CTL_ACTION";
public static final String UPDATE_ACTION="com.fengray.action.UPDATE_ACTION";
//获得界面上的显示歌曲的标题、作者文本框
private TextView titleTV;
private TextView authorTv;
//播放暂停停止按钮
private ImageButton playbtn,stopbtn;
private ActivityReceiver activityReceicer;
//定义音乐的播放状态,0x11代表没有播放,0x12表示正在播放,0x13代表暂停
int status=0x11;
String [] titleStrs=new String[]{"心愿","约定","美丽新世界"};
String [] authorStrs=new String[]{"未知艺术家","周会","伍佰"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playbtn=findViewById(R.id.playbtn);
stopbtn=findViewById(R.id.stopbtn);
titleTV=findViewById(R.id.titleTv);
authorTv=findViewById(R.id.authorTv);
View.OnClickListener listener=new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建intent
Intent intent=new Intent(CTL_ACTION);
intent.setPackage("com.fengray.myex022musicplayer");
switch (view.getId()){
//单击播放/暂停按钮
case R.id.playbtn:
intent.putExtra("control",1);
break;
case R.id.stopbtn:
intent.putExtra("control",2);
break;
}
sendBroadcast(intent);
}
};
//为两个按钮的单击事件添加监听器
playbtn.setOnClickListener(listener);
stopbtn.setOnClickListener(listener);
activityReceicer=new ActivityReceiver();
//创建intentFilter,因此在manifest文件中不要在创建service下的intentfilter项了
IntentFilter filter=new IntentFilter();
//指定BroadCastRecive监听的Action
filter.addAction(UPDATE_ACTION);
//注册broadcastreceiver
registerReceiver(activityReceicer,filter);
Intent intent=new Intent(this,MusicService.class);
//启动后台Service
startService(intent);
}
//自定义的BroadCastReceiver,负责监听从Service穿回来的广播
class ActivityReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//获取Intent中的update消息,update代表播放状态
int update =intent.getIntExtra("update",-1);
//获取Intent中的current消息,current代表当前正在播放的歌曲
int current=intent.getIntExtra("current",-1);
if (current>=0){
titleTV.setText(titleStrs[current]);
authorTv.setText(authorStrs[current]);
}
switch (update){
//播放
case 0x11:
playbtn.setImageResource(R.drawable.play);
status=0x11;
break;
//暂停
case 0x12:
playbtn.setImageResource(R.drawable.pause);
status=0x12;
break;
//暂停状态下设置使用播放图标
case 0x13:
playbtn.setImageResource(R.drawable.play);
status=0x13;
break;
}
}
}
}
2、创建自己的service类,继承自BroadCastReceiver
public class MusicService extends Service {
private MyReceiver serviceReceiver;
private AssetManager assetManager;
private String [] musics=new String[]{"wish.mp3","promise.mp3","beautiful.mp3"};
private MediaPlayer mMediaPlayer;
//当前的状态,0x11表示没有播放,0x12表示正在播放,0x13表示暂停
private int status=0x11;
//记录当前正在播放的音乐
private int current=0;
public MusicService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
assetManager=getAssets();
//创建BroadcastReceiver
serviceReceiver=new MyReceiver();
//创建IntentFilter
IntentFilter filter=new IntentFilter();
filter.addAction(MainActivity.CTL_ACTION);
registerReceiver(serviceReceiver,filter);
//创建Mediaplayer
mMediaPlayer=new MediaPlayer();
//为Mediaplyer指定播放完成时间绑定监听器,这是一个轮播时间,一首播完下一首的事件
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
current++;
if (current>=3){
current=0;
}
//发送广播通知activity更改文本框
Intent sendIntent=new Intent(MainActivity.UPDATE_ACTION);
sendIntent.setPackage("com.fengray.myex022musicplayer");
sendIntent.putExtra("current",current);
//发送广播,将被Activity组件中的BroadCastReceiver接收到
sendBroadcast(sendIntent);
//准备并播放音乐
prepareAndPlay(musics[current]);
}
});
}
class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
int control=intent.getIntExtra("control",-1);
switch (control){
//播放或暂停
case 1:
switch (status){
//原来处于没有播放状态
case 0x11:
//准备并播放音乐
prepareAndPlay(musics[current]);
status=0x12;
break;
//原来处于播放状态
case 0x12:
mMediaPlayer.pause();
//改变为暂停状态
status=0x13;
break;
//原来处于暂停状态
case 0x13:
mMediaPlayer.pause();
//改变为暂停状态
status=0x12;
break;
}
break;
//停止声音
case 2:
//如果原来正在播放或暂停
if(status==0x12 || status==0x13){
//停止播放
mMediaPlayer.stop();
status=0x11;
}
break;
}
//广播通知activity改变图标、文本框
Intent sendIntent=new Intent(MainActivity.UPDATE_ACTION);
sendIntent.setPackage("com.fengray.myex022musicplayer");
sendIntent.putExtra("update",status);
sendIntent.putExtra("current",current);
//发送广播,将被activity组件中的BroadCastReceiver接收到
sendBroadcast(sendIntent);
}
}
private void prepareAndPlay(String music){
try {
//打开指定音乐文件
AssetFileDescriptor assetFileDescriptor=assetManager.openFd(music);
mMediaPlayer.reset();
//使用Mediaplayer加载指定的声音文件
mMediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),assetFileDescriptor.getStartOffset(),
assetFileDescriptor.getDeclaredLength());
//准备声音
mMediaPlayer.prepare();
//播放
mMediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3、布局文档
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/titleTv"
android:text="title"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/authorTv"
android:text="author"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageButton
android:id="@+id/playbtn"
android:src="@drawable/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageButton
android:id="@+id/stopbtn"
android:src="@drawable/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>