1.广播与广播接收者
1.API
静态注册广播接收者
清单文件中配置:
<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">receiver</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"包名.广播接收者文件"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">intent-filter</span> <span class="hljs-attribute">android:priority</span>=<span class="hljs-value">"广播拦截的优先级(最大:2147483647)"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"广播监听的动作 可以是自定义的或者系统广播"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"></<span class="hljs-title">receiver</span>></span></code>
动态注册广播接收者
1.动态创建一个广播接收者
<code class="hljs axapta has-numbering"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyReceiver</span> <span class="hljs-inheritance"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">BroadcastReceiver</span> {</span> @Override <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onReceive(Context context, Intent intent) { <span class="hljs-comment">//收到广播后 </span> <span class="hljs-comment">//1.可以触发某些事件</span> <span class="hljs-comment">//2.从initen参数中获取广播发送的数据</span> } };</code>
2.对广播接收者进行动态注册
<code class="hljs mel has-numbering"> Receiver = new MyReceiver(); <span class="hljs-comment">//设置filter信息</span> IntentFilter <span class="hljs-keyword">filter</span> = new IntentFilter(); <span class="hljs-keyword">filter</span>.addAction(<span class="hljs-string">"自定义的或者系统广播"</span>); <span class="hljs-comment">//设置广播监听的动作</span> <span class="hljs-comment">//注册</span> registerReceiver(Receiver, <span class="hljs-keyword">filter</span>);</code> <ul class="pre-numbering" style=""><li> </li></ul>
3.取消注册
<code class="hljs fix has-numbering"><span class="hljs-attribute">unregisterReceiver(mReceiver); mReceiver </span>=<span class="hljs-string"> null;</span></code>
自定义广播发送(通过intent携带数据)
<code class="hljs cs has-numbering"> Intent intent = <span class="hljs-keyword">new</span> Intent(); intent.putExtra(<span class="hljs-string">"键"</span>, 要携带到接收者的信息); intent.setAction(<span class="hljs-string">"自定义广播"</span>); <span class="hljs-comment">//设置广播监听的动作</span> sendBroadcast(intent);</code>
两种广播的区别
静态注册广播接收者在程序的整个运行期间都会监听。
动态注册的广播接收者可以控制在需要的时候开启监听,不需要的时候关闭监听。通常可以将动态注册广播接收者放到一个服务中,服务开启时注册广播,服务关闭时取消注册。
2.例子
常见系统广播
//监听系统启动广播
<code class="hljs xml has-numbering"> <span class="hljs-tag"><<span class="hljs-title">receiver</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".receiver.BootCompleteReceiver"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.intent.action.BOOT_COMPLETED"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"></<span class="hljs-title">receiver</span>></span></code>
//监听短信
<code class="hljs xml has-numbering"> <span class="hljs-tag"><<span class="hljs-title">receiver</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".receiver.SmsReceiver"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">intent-filter</span> <span class="hljs-attribute">android:priority</span>=<span class="hljs-value">"2147483647"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.provider.Telephony.SMS_RECEIVED"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"></<span class="hljs-title">receiver</span>></span></code>
//获取管理员权限 MyAdminReceiver需要实现但是不用写内容
<code class="hljs xml has-numbering"> <span class="hljs-tag"><<span class="hljs-title">receiver </span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".receiver.MyAdminReceiver"</span> <span class="hljs-attribute">android:description</span>=<span class="hljs-value">"@string/sample_device_admin_description"</span> <span class="hljs-attribute">android:label</span>=<span class="hljs-value">"@string/sample_device_admin"</span> <span class="hljs-attribute">android:permission</span>=<span class="hljs-value">"android.permission.BIND_DEVICE_ADMIN"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">meta-data </span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.app.device_admin"</span> <span class="hljs-attribute">android:resource</span>=<span class="hljs-value">"@xml/device_admin_sample"</span> /></span> <span class="hljs-tag"><<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.app.action.DEVICE_ADMIN_ENABLED"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"></<span class="hljs-title">receiver</span>></span></code>
//监听创建快捷方式
<code class="hljs xml has-numbering"> <span class="hljs-tag"><<span class="hljs-title">receiver</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".receiver.MyWidget"</span> ></span> <span class="hljs-tag"><<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.appwidget.action.APPWIDGET_UPDATE"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"><<span class="hljs-title">meta-data </span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.appwidget.provider"</span> <span class="hljs-attribute">android:resource</span>=<span class="hljs-value">"@xml/process_widget_provider"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">receiver</span>></span></code>
//监听杀死所有进程
<code class="hljs xml has-numbering"> <span class="hljs-tag"><<span class="hljs-title">receiver</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".receiver.KillProcess"</span>></span> <span class="hljs-tag"><<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"com.example.mobilesafe.KILLALLPROCESS"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">intent-filter</span>></span> <span class="hljs-tag"></<span class="hljs-title">receiver</span>></span></code> <ul class="pre-numbering" style=""><li> </li></ul>
动态注册广播接收者(一般在服务中动态注册 重要)
适用情况: 广播接收者监听事件变化,有变化后就返回给服务,服务通过返回Bind或者写SharePrecefence等方法传出数据。
具体运用举例:
1.开启电话监听,监听来电去电 ,例如 黑名单,归属地查询等
2.程序加锁 ,监听当前栈顶程序是否被加锁
3.实时定位 ,不断读取当前定位信息
4.锁屏事件 ,监听到锁屏后可以做一些清理工作
5.和桌面上的Widget通信
两种注册类型的区别:
静态注册是当程序关闭后,如果有广播发过来,还能启动程序
动态注册的生命周期跟程序的生命周期是一样的,程序关闭后动态注册的广播是不能在接收到广播的
动态注册的优点:在Android的广播机制中,动态注册的优先级高于静态注册的优先级,因此在必要情况下,我们需要动态注册广播接收器。
静态注册的有点:动态注册广播接收器还有一个优点就是当用来注册广播的Activity关闭后,广播也就失效了,同时反映了静态注册广播的一个优势,就是无需担心广播接收器是否关闭,只要设备处于开启状态,广播接收器就能接收。
操作频繁的广播事件,如果只是在清单配置文件配置,是不生效的。需要使用代码注册才能生效;
步骤:
<code class="hljs axapta has-numbering"> 例<span class="hljs-number">1</span>:<span class="hljs-comment">// 监听屏幕开关</span> <span class="hljs-comment">// 1、得到广播接收者的对象</span> ScreenBroadCastReceiver screenReceiver = <span class="hljs-keyword">new</span> ScreenBroadCastReceiver(); <span class="hljs-comment">// 2、创建一个intentFilter对象</span> IntentFilter filter = <span class="hljs-keyword">new</span> IntentFilter(); <span class="hljs-comment">// 3、注册接收的事件类型</span> filter.addAction(<span class="hljs-string">"android.intent.action.SCREEN_ON"</span>); filter.addAction(<span class="hljs-string">"android.intent.action.SCREEN_OFF"</span>); <span class="hljs-comment">// 4、注册广播接收者</span> <span class="hljs-keyword">this</span>.registerReceiver(screenReceiver, filter); 例<span class="hljs-number">2.</span><span class="hljs-comment">// 注册监听去电的广播</span> mReceiver = <span class="hljs-keyword">new</span> OutCallReceiver(); IntentFilter filter = <span class="hljs-keyword">new</span> IntentFilter(); filter.addAction(Intent.ACTION_NEW_OUTGOING_CALL); registerReceiver(mReceiver, filter); 以上两例需要我们自己实现广播接收者,下面这个例子中系统为我们实现了回调方法 例<span class="hljs-number">3.</span> <span class="hljs-comment">//来电话</span> mListener = <span class="hljs-keyword">new</span> MyPhoneStateListener(); mTM.listen(mListener, PhoneStateListener.LISTEN_CALL_STATE);<span class="hljs-comment">// 监听来电状态</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyPhoneStateListener</span> <span class="hljs-inheritance"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">PhoneStateListener</span> {</span> @Override <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onCallStateChanged(<span class="hljs-keyword">int</span> state, String incomingNumber) { <span class="hljs-keyword">switch</span> (state) { <span class="hljs-keyword">case</span> TelephonyManager.CALL_STATE_RINGING:<span class="hljs-comment">// 电话玲响</span> <span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> TelephonyManager.CALL_STATE_IDLE:<span class="hljs-comment">// 通话结束</span> <span class="hljs-keyword">break</span>; <span class="hljs-keyword">default</span>: <span class="hljs-keyword">break</span>; } <span class="hljs-keyword">super</span>.onCallStateChanged(state, incomingNumber); } } 例<span class="hljs-number">4.</span><span class="hljs-comment">//设置快捷方式</span> Intent intent = <span class="hljs-keyword">new</span> Intent( <span class="hljs-string">"com.android.launcher.action.INSTALL_SHORTCUT"</span>); <span class="hljs-comment">// 设置快捷方式的图标</span> intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, BitmapFactory .decodeResource(getResources(), R.drawable.home_tools)); <span class="hljs-comment">// 设置快捷方式名称</span> intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, <span class="hljs-string">"黑马小卫士"</span>); <span class="hljs-comment">//不允许重复</span> intent.putExtra(<span class="hljs-string">"duplicate"</span>, <span class="hljs-keyword">false</span>); <span class="hljs-comment">// 动作,跳转主页面</span> Intent actionIntent = <span class="hljs-keyword">new</span> Intent(); actionIntent.setClass(<span class="hljs-keyword">this</span>,MainActivity.class); <span class="hljs-comment">//actionIntent.setAction("com.example.mobilesafe.MAIN");// 通过action启动主页面,需要在清单文件配置action</span> <span class="hljs-comment">//actionIntent.addCategory(Intent.CATEGORY_DEFAULT);// 必须配置categroy</span> intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, actionIntent); <span class="hljs-comment">// 发送广播</span> sendBroadcast(intent);</code>
2.服务
2.1 API
注册一个服务
<code class="hljs java has-numbering">清单文件 <service android:name=<span class="hljs-string">".service.MyService"</span> /> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyService</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Service</span> {</span> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> IBinder <span class="hljs-title">onBind</span>(Intent intent) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>; } <span class="hljs-comment">//创建服务的时候调用</span> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>() { System.out.println(<span class="hljs-string">"*****onCreate******"</span>); <span class="hljs-keyword">super</span>.onCreate(); } <span class="hljs-comment">//启动server 每次start都会调用一次</span> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">onStartCommand</span>(Intent intent, <span class="hljs-keyword">int</span> flags, <span class="hljs-keyword">int</span> startId) { System.out.println(<span class="hljs-string">"*****onStartCommand******"</span>); <span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.onStartCommand(intent, flags, startId); } <span class="hljs-comment">//手动停止程序后会终止服务,会调用onDestroy()方法</span> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDestroy</span>() { System.out.println(<span class="hljs-string">"*****onDestroy******"</span>); <span class="hljs-keyword">super</span>.onDestroy(); } }</code>
开启一个服务
<code class="hljs actionscript has-numbering"> <span class="hljs-number">1.</span>启动 <span class="hljs-comment">//使用Intent</span> Intent intent = <span class="hljs-keyword">new</span> Intent(当前Activity.<span class="hljs-keyword">this</span>, MyService.<span class="hljs-keyword">class</span>); startService(intent); stopService(intent); <span class="hljs-number">2.</span>使用bind让其他组件获取服务提供的数据 <span class="hljs-comment">//使用Intent</span> Intent intent = <span class="hljs-keyword">new</span> Intent(当前Activity.<span class="hljs-keyword">this</span>, MyService.<span class="hljs-keyword">class</span>); bindService(intent, conn, BIND_AUTO_CREATE); unbindService(conn);</code><ul class="pre-numbering" style=""><li> </li></ul>
注意事项
bindService绑定服务、unBindService解除绑定的服务;
服务是在被绑定的时候被创建,调用oncreate、onbind方法;
服务只能被绑定一次;
服务只能被解除一次,接触绑定的时候调用onUnbind、onDestrory方法,如果多次解除绑定会抛出异常;
推荐的方式(启用顺序):
1.startService:开启并创建一个服务,服务长期运行在后台;
2.bindService:绑定服务,可以调用服务里面的方法;
3.unBindService:解除服务,停止服务里面的方法;
4.stopService:停止服务,销毁服务对象;
获取服务中的数据(与服务通信)
<code class="hljs axapta has-numbering">MyService中 <span class="hljs-comment">//这个函数用于返回数据</span> <span class="hljs-keyword">public</span> IBinder onBind(Intent intent) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> MyBind(); <span class="hljs-comment">//返回到前台的对象,包含要执行的service中的方法</span> } <span class="hljs-comment">//继承Binder类,这是因为要返回一个实现IBinder类型接口的</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyBind</span> <span class="hljs-inheritance"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">Binder</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> callPaly() { paly(); } } 客户端 <span class="hljs-comment">//绑定服务</span> bindService(intent, <span class="hljs-keyword">new</span> MyServiceConnection(), BIND_AUTO_CREATE); <span class="hljs-comment">//获取服务返回的数据</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyServiceConnection</span> <span class="hljs-inheritance"><span class="hljs-keyword">implements</span></span> <span class="hljs-title">ServiceConnection</span> {</span> @Override <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onServiceConnected(ComponentName name, IBinder service) { <span class="hljs-comment">//返回服务中包含要调用方法的类</span> serverRet = (MyBind) service; } @Override <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onServiceDisconnected(ComponentName name) { }</code>
aidl 获取其他进程服务的信息
3.内容提供者
3.1API
1.内容解释者
作用: 用来解析内容观察者提供的数据库信息
<code class="hljs axapta has-numbering">ContentResolver contentResolver = getContentResolver(); <span class="hljs-comment">//getContentResolver();是上下文中携带的方法,用于处理内容提供者提供的访问方式。</span> 寻找哪个内容提供者需要用通过uri,uri路径分文 <span class="hljs-string">"主机名"</span>+<span class="hljs-string">"具体要操作的数据"</span> 其中<span class="hljs-string">"主机名"</span>在提供数据库程序的清单文件中定义,<span class="hljs-string">"具体要操作的数据"</span>在这个程序的源码中(一般文件名有provide字样), 我们可以通过查找<span class="hljs-string">"UriMatcher"</span>函数搜索相关的信息。 Uri uri = Uri.parse(<span class="hljs-string">"content://.../"</span>); <span class="hljs-comment">//指定查询哪个应用下数据库的哪个表</span> Cursor cursor = contentResolver.query(uri, ... ...); <span class="hljs-number">2.</span>内容观察者 <span class="hljs-comment">//注册内容观察者</span> getContentResolver().registerContentObserver(uri, <span class="hljs-keyword">true</span>, <span class="hljs-keyword">new</span> MyObeserver(<span class="hljs-keyword">new</span> Handler())); <span class="hljs-comment">//收到通知后回调其中的方法</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyObeserver</span> <span class="hljs-inheritance"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">ContentObserver</span> {</span> <span class="hljs-keyword">public</span> MyObeserver(Handler handler) { <span class="hljs-keyword">super</span>(handler); } <span class="hljs-comment">//发现监视路径下的数据库发生变化就会调用此方法 </span> @Override <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onChange(<span class="hljs-keyword">boolean</span> selfChange) { <span class="hljs-keyword">super</span>.onChange(selfChange); } } <span class="hljs-comment">//在数据库操作中发出信号,通知观察者</span> <span class="hljs-comment">// 通知观察者,数据发生变化了</span> Context.getContentResolver().notifyChange(Uri.parse(<span class="hljs-string">"content://..."</span>),<span class="hljs-keyword">null</span>);</code> <ul class="pre-numbering" style=""><li>32</li></ul>
3.2应用场合举例
1.查询联系人数据库
2.查询短信数据库
3.音乐文件
自定义的数据库我们直接使用SQLiteOpenHelper进行查询
4.意图 的一些应用场合和分类
隐式意图
开启其他应用
<code class="hljs java has-numbering"> 安装程序 <span class="hljs-javadoc">/** * 使用隐式题图安装指定路径下的apk *<span class="hljs-javadoctag"> @param</span> path */</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">installApk</span>(String path) { File file = <span class="hljs-keyword">new</span> File(path); Intent intent = <span class="hljs-keyword">new</span> Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file),<span class="hljs-string">"application/vnd.android.package-archive"</span>); <span class="hljs-comment">//startActivity(intent);</span> startActivityForResult(intent, <span class="hljs-number">0</span>); } 卸载程序 <span class="hljs-javadoc">/** * 卸载应用 */</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">uninstall</span>(String packageName) { <span class="hljs-comment">// 跳转到卸载页面</span> Intent intent = <span class="hljs-keyword">new</span> Intent(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setData(Uri.parse(<span class="hljs-string">"package:"</span> + packageName)); startActivityForResult(intent, <span class="hljs-number">0</span>); } 清理缓存 <span class="hljs-comment">// 清理单个文件缓存</span> <span class="hljs-comment">// 跳转到系统设置页面</span> Intent intent = <span class="hljs-keyword">new</span> Intent(); intent.setAction(<span class="hljs-string">"android.settings.APPLICATION_DETAILS_SETTINGS"</span>); intent.setData(Uri.parse(<span class="hljs-string">"package:"</span> + info.packageName)); intent.addCategory(Intent.CATEGORY_DEFAULT); startActivity(intent); 打电话 Intent intent = <span class="hljs-keyword">new</span> Intent(Intent.ACTION_DIAL); intent.setAction(Intent.ACTION_DIAL); intent.setData(Uri.parse(<span class="hljs-string">"tel:"</span>+number)); startActivity(intent);</code>
显式意图
...
发送广播
例子见第一章
开启服务
例子见第二章
带返回值的开启新的Activity
1.A页面跳转到B:
<code class="hljs actionscript has-numbering">Intent intent = <span class="hljs-keyword">new</span> Intent(AActivity.<span class="hljs-keyword">this</span>, BActivity.<span class="hljs-keyword">class</span>); <span class="hljs-comment">// 如果需要返回数据,用此方法发送intent 第二个参数为发送码</span> startActivityForResult(intent, <span class="hljs-number">2</span>);</code>
2.B页面发送数据给A,B页面关闭:
<code class="hljs r has-numbering">Intent intent = new Intent(); intent.putExtra(<span class="hljs-string">"..."</span>, <span class="hljs-keyword">...</span>); setResult(<span class="hljs-number">2</span>, intent); finish();</code>
3.A页面接收B传来的数据:
在A页面的类中复写以下方法,通过发送码或者返回码判断接收到数据的流向
<code class="hljs r has-numbering"> @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { <span class="hljs-keyword">if</span>(resultCode == <span class="hljs-number">1</span>) { <span class="hljs-keyword">...</span> }<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(resultCode == <span class="hljs-number">2</span>){ <span class="hljs-keyword">...</span> } super.onActivityResult(requestCode, resultCode, data); }</code>
这里写代码片