一、关于Service的那些事
什么是Service?
Service是Android中实现程序后台运行的解决方案,适合去执行那些不需要和用户交互而且还要求长期运行的任务。
它并不是运行在独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。
服务并不会自动开启线程,所有的代码默认运行在主线程中。
启动和停止Service的两种方式
1.Started:
context.startService() ;
context.stopService() ;
该方法适用于服务和activity之间没有调用交互的情况
2.Bound:
context.bindService();
context.unbindService() ;
该方式可以传递参数或者方法调用,通过ServiceConnection的内部类实现来连接Service和Activity。
intentservice
intentservice是service的子类,用来处理异步消息。有个onHandleIntent方法,类似于MessageQueue。IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程
实例:
public class ServiceDemo extends Service{
@Override
public void onCreate() {
super.onCreate();
mMediaPlayer = MediaPlayer.create(this,R.raw.faded);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mMediaPlayer.start();
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
mMediaPlayer.stop();
super.onDestroy();
}
public class LocalBinder extends Binder{
MusicService getService(){
return MusicService.this;
}
}
}
二、BroadcastReceiver应用详解
什么是 BroadcastReceiver?
广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用 Context.sendBroadcast() 、Context.sendOrderedBroadcast() 来实现的。通常一个广播 Intent 可以被订阅了此 Intent 的多个广播接收者所接收。
两者注册方式
第一种——动态注册:
public class MyBroadcastReceiver extends BroadcastReceiver {
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals( SMS_RECEIVED )) {
// 相关处理 : 地域变换、电量不足、来电来信;
}
}
}
第二种——系统注册:
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter >
< action android:name = " android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="main_activity_update_ui" />
</ intent-filter >
</ receiver >
两者的区别:
静态注册的广播一直有效,动态注册的广播需要反注册掉,不然注册在内存里,会不断的消耗内存,所以常用动态注册。
接收广播onReceive方法
发送:
@Override
public void onClick(View view) {
/* 发送广播 */
Intent intent = new Intent(MainActivity.this,TestBroadcastReceiver.class);
//只发给action为COM_EXAMPLE_TEST_BROADCAST
intent.setAction(COM_EXAMPLE_TEST_BROADCAST);
intent.putExtra("toast", "this is a toast of broadcast");
sendBroadcast(intent);
}
接收:
public class TestBroadcastReceiver extends BroadcastReceiver {
/* 接收广播、处理数据 */
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null){
//判断字符串是否相等TextUtils.equals().
if (TextUtils.equals(intent.getAction(),MainActivity.COM_EXAMPLE_TEST_BROADCAST)){
String toastString = intent.getStringExtra("toast");
Toast.makeText(context,toastString,Toast.LENGTH_SHORT).show();
}
}
}
}
三、强大的webView
什么是WebView
Webview能加载显示网页,可以把它视为一个浏览器
可以通过 webView.loadUrl("http://www.baidu.com");来显示网页
也可以通过 webView.loadUrl("file:///android_asset/aa.html");来调用本地的网页
注意:需要在AndroidMainfest.XMl中添加权限
<uses-permission android:name="android.permission.INTERNET" />
代码例子:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web);
mWebView = (WebView) findViewById(R.id.web);
mWebView.loadUrl("http://www.baidu.com");
mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//拦截网页(重新加载网页)
return super.shouldOverrideUrlLoading(view, url);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
//可以在页面开始时候进行操作
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
//页面结束时候
super.onPageFinished(view, url);
}
@Override
public void onLoadResource(WebView view, String url) {
//加载资源
super.onLoadResource(view, url);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
//拦截请求
return super.shouldInterceptRequest(view, request);
}
});
}
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
// 设置进度
super.onProgressChanged(view, newProgress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
//拿到网页标题
super.onReceivedTitle(view, title);
}
@Override
public void onCloseWindow(WebView window) {
super.onCloseWindow(window);
}
});
四、Android 的酷特性widget
什么是widget
就是桌面上的一些小部件。
widget需要在AndroidManifest中注册
<receiver android:name=".MusicWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="main_activity_update_ui" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/music_widget_info" />
</receiver>
Widget配置文件
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:initialLayout = "@layout/layout_widget"
android:minHeight = "100dp"
android:minWidth = "200dp"
android:previewImage = "@drawable/icon"
android:updatePeriodMillis = "20000"
android:widgetCategory = "home_screen">
</appwidget-provider>
主要方法
public class ExampleAppWidgetProvider extends AppWidgetProvider {
/*
* 在3种情况下会调用OnUpdate()。onUpdate()是在main线程中进行,因此如果处理需要花费时间多于10秒,处理应在service中完成。
*(1)在时间间隔到时调用,时间间隔在widget定义的android:updatePeriodMillis中设置;
*(2)用户拖拽到主页,widget实例生成。无论有没有设置Configure activity,我们在Android4.4的测试中,当用户拖拽图片至主页时,widget实例生成,会触发onUpdate(),然后再显示activity(如果有)。这点和资料说的不一样,资料认为如果设置了Configure acitivity,就不会在一开始调用onUpdate(),而实验显示当实例生成(包括创建和重启时恢复),都会先调用onUpate()。在本例,由于此时在preference尚未有相关数据,创建实例时不能有效进行数据设置。
*(3)机器重启,实例在主页上显示,会再次调用onUpdate()
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
// widget被删除时调用
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
Log.d(TAG, "onDeleted(): appWidgetIds.length=" + appWidgetIds.length);
super.onDeleted(context, appWidgetIds);
}
// 最后一个widget被删除时调用
@Override
public void onDisabled(Context context) {
Log.d(TAG, "onDisabled");
super.onDisabled(context);
}
// 第一个widget被创建时调用
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}
// 接收广播的回调函数
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
}