[快捷键]
Ctrl+shift+a 查找键
Ctrl+shift+c 将参数转换成变量
Ctrl+alt+L 格式化代码
4.1 service
Service既不是进程也不是线程,最合适的场景是听歌,它比Activity有更高级的优先级。后台长期运行。
4.1.1 Service生命周期
onCreate()事件回调函数: Service的生命周期开始,完成Service的初始化工作
onStart()事件回调函数:活动生命周期开始,但没有与之对应的“停止”函数,因此可以近似认为活动生命周期也是以onDestroy()标志结束
onDestroy()事件回调函数: Service的生命周期结束,释放Service所有占用的资源
4.1.2 Service服务启动的两种方式
Start :通过调用Context.startService()启动Service,通过调用Context.stopService()或Service.stopSelf()停止Service
Bound:使用Service的组件通过Context.bindService()建立服务链接,通过Context.unbindService()停止服务链接
如果在绑定过程中Service没有启动,Context.bindService()会自动启动Service
4.1.3 启动Service
显示启动:在Intent中指明Service所在的类,并调用startService(Intent)函数启动Service
- final Intent serviceIntent = new Intent(this, RandomService.class);
- startService(serviceIntent);
隐式启动:在注册Service时,声明Intent-filter的action属性
- <service android:name=".RandomService">
- <intent-filter>
- <action android:name="edu.hrbeu.RandomService" />
- </intent-filter>
- </service>
隐式启动的代码如下
- final Intent serviceIntent = new Intent();
- serviceIntent.setAction("edu.hrbeu.RandomService");
4.1.4 案例实现
利用Service实现后台音乐播放
【注意】
1、 myMediaPlayer=MediaPlayer.create(this,R.raw.bigbang);用这种方式创建的MediaPlayer可以直接start 。
2、 音频文件存在R.raw.bigbang,注意rae 这个文件夹是我们后创建的,在res文件夹下。
用start的方式
MyService.class
public class MyService extends Service{
private MediaPlayermyMediaPlayer;
@Override
public void onCreate(){
super.onCreate();
myMediaPlayer=MediaPlayer.create(this,R.raw.bigbang);
}
@Override
public int onStartCommand(Intentintent, int flags, int startId){
myMediaPlayer.start();
return super.onStartCommand(intent,flags, startId);
}
@Override
public void onDestroy(){
super.onDestroy();
myMediaPlayer.stop();
}
@Nullable
@Override
public IBinderonBind(Intent intent) {
return null;
}
}
启动及停止服务
View.OnClickListener mListener=new View.OnClickListener() { @Override public void onClick(View v) { switch(v.getId()){ case R.id.start: startService(new Intent(MainActivity.this,MyService.class)); break; case R.id.stop: stopService(new Intent(MainActivity.this,MyService.class)); break; } } };
用Bound的方式
MyService.class
public class MyService extends Service { private MediaPlayer myMediaPlayer; private IBinder mIBinder=new LocalBinder(); @Override public void onCreate() { super.onCreate(); myMediaPlayer=MediaPlayer.create(this,R.raw.bigbang); } @Override public int onStartCommand(Intent intent, int flags, int startId) { myMediaPlayer.start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); myMediaPlayer.stop(); } @Nullable @Override public IBinder onBind(Intent intent) { return mIBinder; } public class LocalBinder extends Binder { MyService getservice(){ return MyService.this; }; } }
启动及停止服务
private ServiceConnection mServiceConnection=new ServiceConnection(){ //服务连接时 @Override public void onServiceConnected(ComponentName name, IBinder service) { MyService.LocalBinder localBinder= (MyService.LocalBinder) service; MyService myService=localBinder.getservice(); } //服务断开连接时 @Override public void onServiceDisconnected(ComponentName name) { } };
View.OnClickListener mListener=new View.OnClickListener() { @Override public void onClick(View v) { switch(v.getId()){ case R.id.start: startService(new Intent(MainActivity.this,MyService.class)); bindService(new Intent(MainActivity.this,MyService.class),mServiceConnection,BIND_AUTO_CREATE); break; case R.id.stop: unbindService(mServiceConnection); stopService(new Intent(MainActivity.this,MyService.class)); break; } } };
4.1.5 IntentService
4.1.6小结
1.Service是进程或线程吗?
不是
2.能做耗时操作吗?
不能,如果要做,必须如下
Thread mThred=new Thread(new Runnable() { @Override public void run() { } }); mThred.start();
3.用它主要来做什么?
在后台长久运行
4.2 BroadcaseReceiver
BroadcastReceiver也就是“广播接收者”的意思,它是用来接收来自系统和应用中的广播,他没有用户界面。 属于android四大组件之一,需要在项目清单中注册。
系统使用了很多广播
通知时间改变
电池电量变低
拍摄了新照片
改变了语言等
创建步骤
1)创建一个类myTestBroadcastReceiver用于继承BroadcastReceiver
public class myTestBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //发送广播 if(intent!=null){ if(TextUtils.equals(intent.getAction(),"demo.service.fxc.myservice.ab")); String toast=intent.getStringExtra("toast"); Toast.makeText(context,toast,Toast.LENGTH_LONG).show(); } } }
2)注册
静态注册:在清单文件中注册
<receiver android:name=".myTestBroadcastReceiver"> <intent-filter> <action android:name="demo.service.fxc.myservice.abc"/> </intent-filter> </receiver>
动态注册:在代码中注册
//动态注册,首先需要过滤 IntentFilter 然后注册 IntentFilter intentFilter=new IntentFilter(); intentFilter.addAction("demo.service.fxc.myservice.abc"); registerReceiver(mMyTestBroadcastReceiver,intentFilter);
两者的区别在于:动态注册建议在onStart注册,在onDestroy注销;
@Override protected void onStart() { super.onStart(); //动态注册,首先需要过滤 IntentFilter 然后注册 IntentFilter intentFilter=new IntentFilter(); intentFilter.addAction("demo.service.fxc.myservice.abc"); registerReceiver(mMyTestBroadcastReceiver,intentFilter); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(mMyTestBroadcastReceiver); }
3)通过sendBroadcast(intent) 广播
//发送广播 Intent intent=new Intent(); intent.setAction("demo.service.fxc.myservice.abc"); intent.putExtra("Toast","歌曲要播放了"); sendBroadcast(intent);
【注意】不能做耗时操作,//发送广播 >10s 则要 new work thread
建议适当的用,不要滥用。
4.3 Webview
WebView(网络视图)能加载显示网页,可以将其视为一个浏览器。它使用了WebKit渲染引擎加载显示网页,实现WebView有以下两种不同的方法:
方法一:
1.首先在项目管理文件中声明权限,否则出现Web page not available错误。
<uses-permission android:name="android.permission.INTERNET"/>
2.在布局文件中声明WebView
3.在Activity中实例化WebView
4.调用WebView的loadUrl( )方法,设置WevView要显示的网页
(1)可以加载线上url
view.loadUrl("http://www.zhihu.com/");
(2)可以加载本地html(在res 文件夹中新建asset文件夹,将资源文件拷贝)
view.loadUrl("file:///android_asset/test.html");
(3)可以和js交互
mWebView.getSettings().setJavaScriptEnabled(true);
5.为了让WebView能够响应超链接功能,调用setWebViewClient( )方法,设置 WebView视图
6.用WebView点链接看了很多页以后为了让WebView支持回退功能,需要覆盖覆盖Activity类的onKeyDown()方法,如果不做任何处理,点击系统回退键,整个浏览器会调用finish()而结束自身,而不是回退到上一页面.
@Override
public void onBackPressed() {
if(mWebView!=null&mWebView.canGoBack())
mWebView.goBack();
else
super.onBackPressed();
}
7.导航和历史记录
public void onBackPressed() { if(mWebView!=null&mWebView.canGoBack()) { WebBackForwardList webBackForwardList=mWebView.copyBackForwardList(); WebHistoryItem webHistoryItem= webBackForwardList.getItemAtIndex(0); String historyUrl= webHistoryItem.getUrl(); mWebView.goBack(); mWebView.goForward(); mWebView.goBackOrForward(+1); mWebView.reload(); } else super.onBackPressed(); }
4.4Android的酷特性widget(窗口小部件)
App Widget是应用程序窗口小部件(Widget)是微型的应用程序视图,它可以被嵌入到其它应用程序中(比如桌面)并接收周期性的更新。你可以通过一个App Widget Provider来发布一个Widget。
主要相关类介绍:
(1)AppWidgetProvider 继承自 BroadcastReceiver,它能接收 widget 相关的广播,例如 widget 的更新、删除、开启和禁用等。
AppWidgetProvider中的广播处理函数如下:
onUpdate :当 widget 更新时被执行。
onReceive(Context, Intent): 接收到任意广播时触发,并且会在上述的方法之前被调用。
总结,AppWidgetProvider继承于 BroadcastReceiver。实际上,AppWidge中的onUpdate()、onEnabled()、onDisabled()等方法都是在onReceive()中调用的;是onReceive()对特定事情的响应函数。
1.新建一个Android工程命名为:Appwidget
public class appWidget extends AppWidgetProvider{ public appWidget() { super(); } @Override public void onReceive(Context context, Intent intent) { super.onReceive(context, intent); if(intent!=null && TextUtils.equals(intent.getAction(),"widget_button_action")) { Toast.makeText(context, "intent_widget_abc", Toast.LENGTH_LONG).show(); //获取布局及控件,修改属性 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.layout_widget); remoteViews.setTextViewText(R.id.widget_textview, "被点击了"); AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(context); ComponentName componentName=new ComponentName(context,appWidget.class); //刷新视图 appWidgetManager.updateAppWidget(componentName,remoteViews); } } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); //更新布局 RemoteViews remoteViews=new RemoteViews(context.getPackageName(),R.layout.layout_widget); Intent intent=new Intent(); intent.setClass(context,appWidget.class); intent.setAction("widget_button_action"); PendingIntent pendingIntent=PendingIntent.getBroadcast(context,0,intent,0); remoteViews.setOnClickPendingIntent(R.id.widget_button,pendingIntent); appWidgetManager.updateAppWidget(appWidgetIds,remoteViews); } }
2.准备素材,一个是Widget的图标,一个是Widget的背景
3.建立Widget内容提供者文件,我们在res下新建一个set_widget.xml
代码如下:
<appwidget-providerxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="140dp"
android:minHeight="140dp"
android:previewImage="@drawable/timg"
android:updatePeriodMillis="200000"
android:widgetCategory="home_screen"
android:initialLayout="@layout/layout_widget">
</appwidget-provider>
其中宽度、长度很清楚,还有android:updatePeriodMillis是自动更新的时间间隔,android:initialLayout是Widget的界面描述文件。
4. 修改layout_widget.xml布局,代码如下:
<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:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="nihao!"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="button"/>
</LinearLayout>
6. 修改配置文件AndroidManifest.xml,代码如下
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activityandroid:name=".MainActivity">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiverandroid:name=".appWidget">
<intent-filter>
<actionandroid:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-dataandroid:name="android.appwidget.provider"
android:resource="@layout/set_widget">
</meta-data>
</receiver>
</application>