极力推荐文章:欢迎收藏
Android 干货分享 java
本篇文章主要介绍 Android
开发中的部分知识点,经过阅读本篇文章,您将收获如下内容:android
- 广播的生命周期
- 四大组件之一,必须在Androidmainfest.xml中注册
- 广播的注册(静态广播、动态广播)
- 广播的发送(正常、有序、持续)
- 广播接收(系统广播、自定义广播)
Broadcast
是 Android
四大组件之一,是一种普遍运用在应用程序之间异步传输信息的机制。Broadcast
本质上是一个Intent
对象,差异在于 Broadcast
能够被多个 BroadcastReceiver
处理。BroadcastReceiver
是一个全局监听器,经过它的 onReceive()
能够过滤用户想要的广播,进而进行其它操做。程序员
BroadcastReceiver
默认是在主线程中执行,若是onReceiver()
方法处理事件超过10s
,则应用将会发生ANR(Application Not Responding)
,此时,若是创建工做线程并不能解决此问题,所以建议:如处理耗时操做,请用 Service
代替。微信
BroadcastReceiver
继承关系 以下:网络
java.lang.Object ↳ android.content.BroadcastReceiver
BroadcastReceiver
的主要声明周期方法onReceiver()
,此方法执行完以后,BroadcastReceiver
实例将被销毁。并发
<receiver android:name="ReceiverMethod" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="String....." /> </intent-filter> </receiver>
注意:
如不注册,将致使没法接收处理广播消息app
广播的注册分两种,一种在ndroidMfest.xml
中静态注册,另外一种是在Java
代码中动态注册。异步
一些系统发送的广播须要在Androidmainfest.xml
中静态注册,例如 开机广播,apk状态改变广播,电量状态改变广播等。这些静态注册的广播,一般在Androidmainfest.xml
中拦截特定的字符串。ide
静态注册广播的方法以下:学习
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.programandroid" android:versionCode="1" android:versionName="1.0" > ... ... <receiver android:name="com.programandroid.BroadcastReceiver.NotificationReceived" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="Notification_cancel" /> <action android:name="Notification_music_pre" /> <action android:name="Notification_music_play" /> <action android:name="Notification_music_next" /> </intent-filter> </receiver> ... ...
开机广播比较特殊,须要在Androidmainfest.xml
中添加权限。不然,没法获取开机广播。
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> //静态注册广播的方法 <receiver android:name=".component.BroadcastReceiver.BootReceiverMethod" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
在Java中动态注册广播,一般格式以下:
//动态注册广播 registerReceiver(BroadcastReceiver, IntentFilter);
在广播中动态注册广播请注意必定要使用context.getApplicationContext()
,防止context
为空 ,引发空指针异常。
public class ScreenOnOffReceiver { public static void ReceiverScreenOnOff(Context context) { IntentFilter screenOffFilter = new IntentFilter(); screenOffFilter.addAction(Intent.ACTION_SCREEN_OFF); screenOffFilter.addAction(Intent.ACTION_SCREEN_ON); BroadcastReceiver mScreenOnOffReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String action = intent.getAction(); if (action.equals(Intent.ACTION_SCREEN_OFF)) { Toast.makeText(context, "接收屏幕熄灭广播", Toast.LENGTH_SHORT).show(); } if (action.equals(Intent.ACTION_SCREEN_ON)) { Toast.makeText(context, "接收屏幕点亮广播", Toast.LENGTH_SHORT).show(); } } }; /** * context.getApplicationContext() * 在广播中注册广播时候须要注意,防止context 为空 ,引发空指针异常 * **/ // 2.动态注册广播的方法 context.registerReceiver(mScreenOnOffReceiver, screenOffFilter); } }
发送无序广播在Android
中很常见,是一种一对多的关系,主要经过 sendBroadcast(intent);
发送广播。
广播说白了就是一个带Action
等字符串标记的Intent
。发送自定义广播举例以下:
Intent customIntent=new Intent(); customIntent.setAction("SendCustomBroadcast"); sendBroadcast(customIntent);
当用户对某些广播感兴趣的话,此时能够获取此广播,而后在onReceive
方法中处理接收广播的一下操做。
public class CustomBroadcast extends BroadcastReceiver { public CustomBroadcast() { } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("SendCustomBroadcast")){ Toast.makeText(context,"自定义广播接收成功:Action:SendCustomBroadcast",Toast.LENGTH_SHORT).show(); } } }
注意自定义广播是在
Androidmanfest.xml
中静态注册的。
广播在Android
是有优先级的,优先级高的广播能够终止或修改广播内容。发送有序广播的方法以下sendOrderedBroadcast(intent,"str_receiver_permission");
Intent customOrderIntent=new Intent(); customOrderIntent.setAction("SendCustomOrderBroadcast"); customOrderIntent.putExtra("str_order_broadcast","老板说:公司每人发 10 个 月饼"); sendOrderedBroadcast(customOrderIntent,"android.permission.ORDERBROADCAST");
广播属于四大组件,必定要在AndroidMainfest.xml
中注册。
接收有序广播的静态注册方法以下:
<receiver android:name=".component.BroadcastReceiver.CustomHightBrodcast" android:enabled="true" android:exported="true" > <intent-filter android:priority="1000"> <action android:name="SendCustomOrderBroadcast" /> </intent-filter> </receiver> <receiver android:name=".component.BroadcastReceiver.CustomMiddleBroadcast" android:enabled="true" android:exported="true" > <intent-filter android:priority="500"> <action android:name="SendCustomOrderBroadcast" /> </intent-filter> </receiver> <receiver android:name=".component.BroadcastReceiver.CustomLowerBroadcast" android:enabled="true" android:exported="true" > <intent-filter android:priority="100"> <action android:name="SendCustomOrderBroadcast" /> </intent-filter> </receiver>
public class CustomHightBrodcast extends BroadcastReceiver { public CustomHightBrodcast() { } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("SendCustomOrderBroadcast")) { Toast.makeText(context, intent.getStringExtra("str_order_broadcast"), Toast.LENGTH_SHORT).show(); Bundle bundle=new Bundle(); bundle.putString("str_order_broadcast","经理说:公司每人发 5 个 月饼"); // 修改广播传输数据 setResultExtras(bundle); } } }
public class CustomMiddleBroadcast extends BroadcastReceiver { public CustomMiddleBroadcast() { } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("SendCustomOrderBroadcast")) { Toast.makeText(context, getResultExtras(true).getString("str_order_broadcast"), Toast.LENGTH_SHORT).show(); Bundle bundle=new Bundle(); bundle.putString("str_order_broadcast","主管说:公司每人发 2 个 月饼"); setResultExtras(bundle); } } }
public class CustomLowerBroadcast extends BroadcastReceiver { public CustomLowerBroadcast() { } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("SendCustomOrderBroadcast")) { String notice= getResultExtras(true).getString("str_order_broadcast"); Toast.makeText(context,notice, Toast.LENGTH_SHORT).show(); // 终止广播继续传播下去 abortBroadcast(); } } }
注意 :
有序广播须要声明并使用权限
<!-- 申请使用自定义 有序广播的权限 --> <uses-permission > android:name="android.permission.ORDERBROADCAST" />
<!-- 自定义 有序广播的权限 --> <permission> android:name="android.permission.ORDERBROADCAST"/>
在有序广播中高优先级的广播接收广播,能够修改数据,而后传给低优先级的广播。
粘性广播会在Android
系统中一直存在,不过随着 Android
系统的不断更新,此方法逐渐被抛弃,使用方法以下:sendStickyBroadcast(intent);
当广播发出后,如何接收广播呢,下面将介绍接收广播的方法。
接受广播类 主要继承 BroadcastReceiver
,而后在onReceive
方法,过滤广播Action
中携带的Intent
,而后进行相关处理。
p ublic class BootReceiverMethod extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 接收开机广播处理事情,好比启动服务 Intent mStartIntent = new Intent(context, StartServiceMethods.class); context.startService(mStartIntent); } }
<receiver android:name=".component.BroadcastReceiver.BootReceiverMethod" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
极力推荐文章:欢迎收藏
Android 干货分享
本篇文章主要介绍 Android
开发中的部分知识点,经过阅读本篇文章,您将收获如下内容:
- Service 简介
- 四大组件之一,必须在Androidmainfest.xml 中注册
- 启动模式启动服务
- 绑定模式绑定服务
- 前台服务
- AIDL远程服务
Service
是 Android
四大组件之一(Activity
活动,Service
服务,ContentProvider
内容提供者,BroadcastReceiver
广播),与Activity
相比,Activity
是运行在前台,用户能够看得见,Service
则是运行在后台,无用户界面,用户没法看到。
Service
主要用于组件之间交互(例如:与Activity
、ContentProvider
、BroadcastReceiver
进行交互)、后台执行耗时操做等(例以下载文件,播放音乐等,但Service
在主线程运行时长不能超过20s
,不然会出现ANR
,耗时操做通常建议在子线程中进行操做)。
在了解Service
的生命周期的以前,咱们先了解一下Service
的继承关系,方便咱们更好的了解Service
。
java.lang.Object ↳ android.content.Context ↳ android.content.ContextWrapper ↳ android.app.Service
Service
有两种不一样的启动模式 ,不一样的启动模式对应不一样生命周期.Service
启动模式主要分两种: 1. 启动模式。 2. 绑定模式。
此模式经过 startService()
方法启动,此服务能够在后台一直运行,不会随启动组件的消亡而消亡。只能执行单一操做,没法返回结果给调用方,经常使用于网络下载、上传文件,播放音乐等。
此模式 经过绑定组件(Activity
等)调用 bindService()
启动,此服务随绑定组件的消亡而解除绑定。
若是此时没有其它经过startService()
启动,则此服务会随绑定组件的消亡而消亡。
多个组件不只能够同时绑定一个Service
,并且能够经过进程间通讯(IPC)
执行跨进程操做等。
启动模式与绑定模式的服务能够同时运行,在销毁服务时,只有两种模式都不在使用Service
时候,才能够销毁服务,不然会引发异常。
两种 Service
模式的生命周期以下:
<manifest ... > ... <application ... > <service android:name=".ServiceMethods" /> ... </application> </manifest>
Service
如不注册 ,不会像Activity
那样会致使App Crash
,Service
不注册 不会报异常信息,可是服务会起不来,如不注意很容易迷惑。
经过启动模式启动的Service
,如不主动关闭,Service
会一直在。
Intent mBindIntent = new Intent(ServiceMethods.this, BindServiceMethods.class); startService(mStartIntent);
下面是验证启动模式启动服务的生命周期的方法,详细生命周期请查看上方Service
的生命周期图。
01-03 17:16:36.147 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onCreate---- 01-03 17:16:36.223 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onStartCommand---- 01-03 17:16:38.174 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onDestroy----
此案例功能:启动服务,在服务中建立通知
// Service 建立方法 @Override public void onCreate() { super.onCreate(); Log.i(TAG, "----onCreate----"); } // Service 启动方法 @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "----onStartCommand----"); // 获取NotificationManager实例 notifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // 实例化NotificationCompat.Builder并设置相关属性 NotificationCompat.Builder builder = new NotificationCompat.Builder( this) // 设置小图标 .setSmallIcon(R.drawable.ic_launcher) .setLargeIcon( BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher)) // 设置通知标题 .setContentTitle("我是经过StartService服务启动的通知") // 设置通知不能自动取消 .setAutoCancel(false).setOngoing(true) // 设置通知时间,默认为系统发出通知的时间,一般不用设置 // .setWhen(System.currentTimeMillis()) // 设置通知内容 .setContentText("请使用StopService 方法中止服务"); // 经过builder.build()方法生成Notification对象,并发送通知,id=1 notifyManager.notify(1, builder.build()); return super.onStartCommand(intent, flags, startId); } // Service 销毁方法 @Override public void onDestroy() { Log.i(TAG, "----onDestroy----"); notifyManager.cancelAll(); super.onDestroy(); }
绑定模式启动的服务会随着绑定逐渐的消亡而解除Service
绑定,若是此时Service
没有经过启动模式启动,则此服务将会被销毁。
绑定模式,是经过其余组件启动的Service
。
// 启动绑定服务处理方法 public void BtnStartBindService(View view) { // 启动绑定服务处理方法 bindService(mBindIntent, serviceConnection, Context.BIND_AUTO_CREATE); isBindService = true; Toast.makeText(ServiceMethod.this, "启动 " + mBindCount + " 次绑定服务", Toast.LENGTH_SHORT).show(); } public void BtnSopBindService(View view) { if (isBindService) { // 解除绑定服务处理方法 unbindService(serviceConnection); Toast.makeText(ServiceMethod.this, "解除 " + mUnBindCount + " 次绑定服务", Toast.LENGTH_SHORT).show(); isBindService = false; } }
绑定服务 随绑定组件的消亡而消亡
// Service 建立方法 @Override public void onCreate() { super.onCreate(); Log.i(TAG, "----onCreate----"); } // Service 绑定方法 @Override public IBinder onBind(Intent intent) { Log.i(TAG, "----onBind----"); MyBinder myBinder = new MyBinder(); return myBinder; } // Service 解除绑定方法 @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "----onUnbind----"); return super.onUnbind(intent); } // Service 销毁方法 @Override public void onDestroy() { Log.i(TAG, "----onDestroy----"); super.onDestroy(); }
绑定服务的生命周期代码打印Log
信息以下:
01-03 20:32:59.422 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onCreate---- 01-03 20:32:59.423 13306-13306/com.android.program.programandroid I/BindService wjwj:: -----onBind----- 01-03 20:33:09.265 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onUnbind---- 01-03 20:33:09.266 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onDestroy----
功能:获取绑定模式启动 绑定服务及解除绑定服务的次数
package com.android.program.programandroid.component.Service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class BindServiceMethods extends Service { private static final String TAG = "BindService wjwj:"; public BindServiceMethods() { } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "----onCreate----"); } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "----onBind----"); MyBinder myBinder = new MyBinder(); return myBinder; } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "----onUnbind----"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.i(TAG, "----onDestroy----"); super.onDestroy(); } }
// 启动绑定服务处理方法 public void BtnStartBindService(View view) { bindService(mBindIntent, serviceConnection, Context.BIND_AUTO_CREATE); isBindService = true; Toast.makeText(ServiceMethods.this,"启动 "+mBindCount+" 次绑定服务",Toast.LENGTH_SHORT).show(); } // 解除绑定服务处理方法 public void BtnSopBindService(View view) { if (isBindService) { unbindService(serviceConnection); Toast.makeText(ServiceMethods.this,"解除 "+mUnBindCount+" 次绑定服务",Toast.LENGTH_SHORT).show(); isBindService=false; } }
Binder
接口类/** * 该类提供 绑定组件与绑定服务提供接口 * */ public class MyBinder extends Binder { private int count = 0; public int getBindCount() { return ++count; } public int getUnBindCount() { return count> 0 ? count-- : 0; } }
服务默认启动方式是后台服务,可是能够经过设置服务为前台服务,提升服务的优先级,进而避免手机内存紧张时,服务进程被杀掉。
1.设置为前台服务
//设置为前台服务 startForeground(int, Notification)
2.取消前台服务
//取消为前台服务 stopForeground(true);
功能:前台服务绑定通知信息,提升服务进程优先级,不然取消通知信息
package com.android.program.programandroid.component.Service; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.IBinder; import android.support.v4.app.NotificationCompat; import com.android.program.programandroid.R; public class MyStartForcegroundService extends Service { public MyStartForcegroundService() { } @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(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent.getAction().equals("start_forceground_service")) { // 获取NotificationManager实例 NotificationManager notifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // 实例化NotificationCompat.Builder并设置相关属性 NotificationCompat.Builder builder = new NotificationCompat.Builder(this) // 设置小图标 .setSmallIcon(R.mipmap.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) // 设置通知标题 .setContentTitle("我是经过startForeground 启动前台服务通知") // 设置通知不能自动取消 .setAutoCancel(false) .setOngoing(true) // 设置通知时间,默认为系统发出通知的时间,一般不用设置 // .setWhen(System.currentTimeMillis()) // 设置通知内容 .setContentText("请使用stopForeground 方法改成后台服务"); //经过builder.build()方法生成Notification对象,并发送通知,id=1 // 设置为前台服务 startForeground(1, builder.build()); } else if (intent.getAction().equals("stop_forceground_service")) { stopForeground(true); } return super.onStartCommand(intent, flags, startId); } }
因为内容较多,后续另开一篇详细介绍。
至此,本篇已结束,若有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!