做网站有什么语言好/关键词优化seo排名
start方式开启服务的生命周期
服务的生命周期:
- 如果采用start的方式开启服务
onCreate()-->onStartCommand()-->onStart()-->onDestory();
- 服务已经被开启,不会重复的创建,多次调用startService方法,服务的onCreate()始终只会执行一次
onCreate()-->
onStartCommand()-->
onStart()-->
onStartCommand()-->
onStart()-->
onStartCommand()-- >
onStart()-->
onDestory();- 服务只会停止一次 多次调用stopService方法是无效的。
代码如下:
package com.li.lifeWeek;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service{@Overridepublic void onCreate() {Log.v("wang", "onCreate 服务器创建的时候调用");}@Overridepublic void onStart(Intent intent, int startId) {Log.v("wang", "onStart 服务器启动的时候被调用 ");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.v("wang", "onStartCommand 服务器启动的时候被调用 ");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {Log.v("wang", "onDestroy 服务器销毁的时候掉用");}@Overridepublic IBinder onBind(Intent intent) {return null;}}
绑定服务调用服务方法的过程
采用startService无法调用
- 通过绑定服务无法返回服务本身
- 通过new无法获取服务的上下文 也就是不是当前服务本身 而只是拿到普通的对象
采用bindService方式
对比:
屁民:想找官员办事(直接找无法找到,找到他的秘书)
官员:为人民服务
秘书:告诉官员办某件事
项目:绑定服务调用服务的方法
步骤:
1.采用bindService的方式开启服务
2.如果服务绑定成功 会调用一个onBind方法,返回一个代理对象
3.在连接监听器中获取代理对象
4.对代理对象调用某个方法 代理对象在该方法内访问服务的方法
采用接口暴露服务里面的方法
- 绑定服务 调用服务方法 的例子
- 我们发现 代理对象的方法我们都可以调用 那为了屏蔽代理对象其他方法 我们必须将其他方法设置为了私有
但是这样还不够彻底 因为我们可以用反射去调用其方法。
- 所以我们可以去创建一个公共接口 这样我们只需要知道接口的方法 到底是那个类在做代理 可以在运行时去指定
bind方式服务的生命周期&混合调用的生命周期
项目准备:服务的生命周期-v2
- 采用bind方式开启服务的生命周期
onCreate()-->onBind()-->onUnbind()-->onDestory()
- bind的方式 只能绑定一次 多次绑定会导致解绑失败
- bind的方式,只能解绑一次 多次解绑 程序会异常退出
- 不求同生 但求同死(Activity挂了 服务就挂了)
- 可以调用服务的方法
混合调用服务的生命周期处理
为了保证服务长期的运行,又想调用服务的方法。
startService() 保证服务长期后台运行
bindService() 绑定服务,调用服务的方法
unbundService() 解绑服务,不需要再去调用方法了
stopService() 停止服务
1.服务有2个特性:
1.后台一直运行
2.没有界面 能够与界面进行交互
两种启动方式
1.startService: 后台一直运行 不能交互数据2.bindService :当启动的组件被摧毁的时候 Service也跟着销毁 能够交互数据
在应用中一般多是 startService调用 bindService
使用混合调用
Service 的生命周期
混合生命周期:(为了让服务能够一直运行 也为了让服务能够与界面UI交互数据 一般需要混合使用两种启动服务的方式)
startService()->bindService()->unBindService()-(服务还存在)-stopService();
onCreate()->onStartCommand()->onBind()->onUnBind()->onDestory();
本地服务和远程服务
1. 从启动方式来说:
开启服务
绑定服务
2. 服务的执行类型:
远程服务(AIDL服务 android interface definition language)
本地服务
绑定服务的应用场景
* 提供一个服务 后台运行里面有一些公共的逻辑供调用
* 1.微信支付/支付宝支付 微信有一个支付的服务,绑定,调用支付的方法(微信App提供了一个服务 大众点评支付的时候调用微信支付)
* 2.sony手机 人脸识别服务 绑定到这个服务传递一个照片 就会把人脸标记出来
* 3.音乐播放器 后台服务里面播放音乐 绑定服务暂停 下一曲 上一曲 (服务与APP的代码都在同一个包里面)
本地服务就是服务器在自己手机了开启的服务 自己调用他
远程服务就是服务器是另外一个软件的一个服务
支付宝远程服务的创建
AIDL:android interfacedefinition language 安卓接口定义语言
远程服务的调用开发步骤:
1. 在支付宝APP里面 创建一个服务 提供一个支付方法(主功能有了 其他应用能拿到服务)
2. 创建代理 为了规范 要先创建一个接口,服务里面有的支付方法 接口也应该用。
3. 为了让其他应用共享数据、服务,需要定义一个共同的规范.aidl (修改文件后缀)
支付宝的服务:
package com.li.zhifubao;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;public class AlipayService extends Service{private class MyAlipayService extends IAlipayService.Stub{@Overridepublic int callSafePay(String account, String pwd, String payPwd, double money, long currTimeMiles) {return safePay(account, pwd, payPwd, money, currTimeMiles);//通关接口的实现方法}}@Overridepublic IBinder onBind(Intent intent) {return new MyAlipayService();}/*** * @param account 账号* @param pwd 密码* @param payPwd 支付密码* @param money 支付金额* @param currTimeMiles 当前的时间撮* @return int* 代码错误 ----- -1* 账号密码错误 ---0* 支付密码错误 ---1* 余额不足 ------2* 支付成功 ------3*/ private int safePay(String account,String pwd,String payPwd,double money,long currTimeMiles){if(!account.equals("zhangsa")||!pwd.equals("123456")){return 0;}if(!payPwd.equals("123456")){return 1;}//如果支付的金额大于一千块就显示余额不足if(money>1000){return 2;}//如果上面的多不满足 说明支付成功return 3;}
}
支付宝绑定服务
<service android:name="com.li.zhifubao.AlipayService"><intent-filter ><action android:name="com.li.zhifubao.AlipayService.SAFEPAY"/><!--对外提供隐士启动com.li.zhifubao.AlipayService类--></intent-filter></service>
支付宝里面的AIDL技术
淘宝里面的调用:
package com.li.taobao;import com.li.zhifubao.IAlipayService;import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.widget.Toast;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void clickPay(View v){Intent intent = new Intent();intent.setAction("com.li.zhifubao.AlipayService.SAFEPAY");//使用隐试启动bindService(intent, new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stub}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {IAlipayService sefePay=IAlipayService.Stub.asInterface(service);try {/*** @return int* 代码错误 ----- -1* 账号密码错误 ---0* 支付密码错误 ---1* 余额不足 ------2* 支付成功 ------3*/int i=sefePay.callSafePay("zhangsa", "123456", "123456", 5000,System.currentTimeMillis());switch (i) {case 0:Toast.makeText(MainActivity.this, "账号或密码错误", Toast.LENGTH_SHORT).show();break;case 1:Toast.makeText(MainActivity.this, "支付密码错误", Toast.LENGTH_SHORT).show();break;case 2:Toast.makeText(MainActivity.this, "余额不足", Toast.LENGTH_SHORT).show();break;case 3:Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();break;default:break;}} catch (RemoteException e) { //该异常叫远程调用的异常// TODO Auto-generated catch blocke.printStackTrace();}}}, BIND_AUTO_CREATE);}
}
音乐播放器的界面
开发步骤:
1. 将音乐放置到sd卡中
2. 创建音乐列表
3. 创建音乐服务 创建播放音乐的方法
4. 创建音乐服务的接口
5. 在音乐点击事件中调用音乐服务的调用
6. 设置播放模式 因为这里涉及到列表循环所以需要列表的信息和当前播放的索引 需要将服务的方法进行修改
7. 在播放的过程中需要在界面左上角添加提示框 因为每次播放都会在服务里面执行 所以可以在播放音乐的代码中弹出提示
8. 退出音乐应用 需要关闭提示框释放音乐资源解绑和停止服务关闭界面
附加知识点:
如何获取菜单的点击事件
如何创建提示栏
代码提示:
package com.li.musicPlay;import java.io.File;
import java.util.ArrayList;import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;public class MainActivity extends Activity implements OnItemClickListener{private ListView mListView;private ArrayList<String> mData;// 存放音乐的路径private MusicAdapter adapter;private ServiceConnection mConn;private IMusicService mIMusic;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 加载UI控件initUI();// 初始化数据initData();//传入列表adapter.setData(mData);adapter.notifyDataSetChanged();//重新调用Adapter对象mListView.setOnItemClickListener(this);//启动服务绑定Intent intent = new Intent(this,MusicService.class);mConn=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stub}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mIMusic = (IMusicService)service;}};bindService(intent, mConn , BIND_AUTO_CREATE);//设置播放的模式 1.播放停止 2.单曲循环 3.全部循环}private void initData() {mData = new ArrayList<String>();// 1.应该找到SD卡的路径File file = Environment.getExternalStorageDirectory();// 2.循环遍历子文件File[] files=file.listFiles();//全部的子文件for(File filsFile : files){// 3.判断文件是否以MP3结尾String fileName=filsFile.getAbsolutePath();if(fileName.endsWith("mp3")){// 4.如果是的话需要将路径添加到mData里面mData.add(fileName);}}}private void initUI() {mListView = (ListView) findViewById(R.id.listViewId);adapter = new MusicAdapter();mListView.setAdapter(adapter);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//拿到代理对象Toast.makeText(this, ""+(String)adapter.getItem(position), Toast.LENGTH_SHORT).show();mIMusic.callPlayMusic(mData, position);}//创建菜单栏 返回true 代表告诉系统我们自己处理 不需要系统插手@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}//菜单栏被点击的时候回调的方法@Overridepublic boolean onOptionsItemSelected(MenuItem item) {SharedPreferences shared = getSharedPreferences("music", MODE_PRIVATE);Editor edit=shared.edit();//状态 0 停止音乐 1 单取循环 2 循环播放 switch (item.getItemId()) {case R.id.stop_when_over:edit.putInt("mode", 0);break;case R.id.single_loop:edit.putInt("mode", 1);break;case R.id.all_loop:edit.putInt("mode", 2);break;case R.id.logout_app://退出应用//退出应用//1.通知栏去掉mIMusic.callStopMusicService();//2.关闭服务unbindService(mConn);Intent intent = new Intent(this,MusicService.class);stopService(intent);//3.界面退出finish();break;}edit.commit();//写入文件中回写sreturn super.onOptionsItemSelected(item);}}
package com.li.musicPlay;import java.util.ArrayList;import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;public class MusicAdapter extends BaseAdapter{private ArrayList<String> mData;public void setData(ArrayList<String> mData) {this.mData=mData;}@Overridepublic int getCount() {return mData!=null?mData.size():0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {TextView textView=null;if(convertView==null){convertView=LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, null);textView=(TextView)convertView.findViewById(android.R.id.text1);convertView.setTag(textView);}else{textView=(TextView)convertView.getTag();}textView.setText(subFileName(mData.get(position))+"");return convertView;}private String subFileName(String subName){return subName.substring(subName.lastIndexOf("/")+1);}@Overridepublic Object getItem(int position) {return mData.get(position)!=null?mData.get(position):null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}}
package com.li.musicPlay;import java.util.ArrayList;import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.IBinder;public class MusicService extends Service{private MediaPlayer mMediaPlayer;private int mCurrentPosition;@Overridepublic IBinder onBind(Intent intent) {return new MusicAgent();}private class MusicAgent extends Binder implements IMusicService{@Overridepublic void callPlayMusic(ArrayList<String> list,int position) {playMusic(list,position);}@Overridepublic void callStopMusicService() {stopMusicService();}}/*** 音乐播放器* @param filePath 传过来的元路径*/public void playMusic(final ArrayList<String> list,final int position){mCurrentPosition=position;showNotification(list.get(mCurrentPosition).substring(list.get(mCurrentPosition).lastIndexOf("/")+1));if(mMediaPlayer == null){mMediaPlayer = new MediaPlayer();//player播放 IDEL空闲状态//当音乐播放完成的时候调用的 根据当前的播放模式来决定是单曲循环还是其他mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {//音乐播放接听器@Overridepublic void onCompletion(MediaPlayer mp) {SharedPreferences shared= getSharedPreferences("music", MODE_PRIVATE);int type=shared.getInt("mode", 0);switch (type) {case 1://单曲循环playMusic(list,mCurrentPosition);//自己调用自己break;case 2://全部循环mCurrentPosition++;//如果加完了 此时索引大于队列的最后一个索引 就要变成0 0停止播放if(mCurrentPosition>list.size()-1){mCurrentPosition=0;}playMusic(list,mCurrentPosition);break;}}});}try {//如果上一次有设置数据源了 再次进来需要重新释放资源mMediaPlayer.reset();mMediaPlayer.setDataSource(list.get(mCurrentPosition));//设置数据元mMediaPlayer.prepare();//装备数据mMediaPlayer.start();//开始播放} catch (Exception e) {e.printStackTrace();}}private void showNotification(String musicName){NotificationManager manager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);Notification notification=new Notification(R.drawable.ic_launcher, musicName+"正在播放...", System.currentTimeMillis());//PendingIntent.FLAG_ONE_SHOT 只显示一次Intent intent = new Intent(this,MainActivity.class);PendingIntent contentIntent =PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);notification.setLatestEventInfo(this, musicName+"正在播放...", musicName+"播放中....", contentIntent);manager.notify(0,notification);}//取消标题栏上面的选项private void CloseShow(){ NotificationManager manager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);manager.cancelAll();}/*** 停止播放 */public void stopMusicService(){//1.取消通知栏CloseShow();//2.释放mMediaPlayer的资源if(mMediaPlayer!=null){mMediaPlayer.stop();//停止音乐服务mMediaPlayer.release();//释放资源mMediaPlayer=null;//重新设为空}}
}
package com.li.musicPlay;import java.util.ArrayList;public interface IMusicService {//调用音乐路径void callPlayMusic(ArrayList<String> list,int position);//退出服务void callStopMusicService();
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ListViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/listViewId"/></LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" ><item android:id="@+id/stop_when_over"android:title="播放停止"/><item android:id="@+id/single_loop"android:title="单曲循环"/><item android:id="@+id/all_loop"android:title="全部循环"/><item android:id="@+id/logout_app"android:title="退出应用"/>
</menu>