进程概念介绍
[1]四大组件是运行在同一个进程里面
[2]四大组件都运行在主线程里面
[3]进程有5种优先级
[1]foreground process 前台进程 优先级最高 最后被杀死
[1.1]用户正在交互 相当于Activity里面的OnResume方法执行了
[1.2]当BroadcastReceiver执行了onRecevier方法执行的时候 也属于前台进程
[2]Visible Process
可视进程 一直能影响用户,看的见,但是不能交互。相当于执行了Activity的onPause方法
[3]service Process 服务进程
[4]background process 后台进程
Activity不可见.相当于Activity执行了onstop
[4]empty process 空进程
进程里面不会维护任何组件。系统不直接杀死空进程.目的是提高应用下次开启的时间
start方式开启服务的特点
[1]定义服务 写一个类继承service
[2]服务第一次运行的时候会执行onCreate和Onstart方法
[3]start-service 开启服务,服务就会在后台长期运行。
[4]多次开启服务,服务只会执行Onstart方法
[5]当Activity退出的时候,服务不会销毁。用户手动停止服务,服务才会销毁。
[6]在应用管理界面可以停止服务
[7]或者调用stop停止服务
线程:也没有界面
与服务的区别:比服务进程优先级低
电话窃听器
[1]TelephonyManager 可以获取电话的状态,也可以获取其他修改电话的信息 [2]这个类不可以new 需要通过getSystemService方法调用 PhoneService: @Override public void onCreate() { super.onCreate(); // [1]创建一个电话管理器 TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); // [2]给电话管理器添加一个监听器 // 参数1:电话监听器 // 参数2:监听电话的什么状态 tm.listen(new PhoneStateListener() { @Override public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_IDLE:// 空闲 if (recorder != null) { // [8]停止录 recorder.stop(); // [9]重置录音机 recorder.reset(); // [10]释放录音机资源 recorder.release(); } System.out.println("停止录"); break; case TelephonyManager.CALL_STATE_OFFHOOK: // 接听 // [7]开始录 recorder.start(); System.out.println("开始录"); break; case TelephonyManager.CALL_STATE_RINGING: // 响铃 try { recorder = new MediaRecorder(); // [2]设置音频源 mic=麦克风(只能录一个人说话)VOICE_CALL(可以录俩人说话 ) recorder.setAudioSource(MediaRecorder.AudioSource.MIC); // [3]设置音频源的输出格式GPP=3gp recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); // [4]设置音频源的编码方式 如果没有需求 采用默认 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // [5]设置音频保存的路径 recorder.setOutputFile("/mnt/sdcard/luyin.3gp"); // [6]录音器开始准备 recorder.prepare(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("准备录"); break; } } }, PhoneStateListener.LISTEN_CALL_STATE); } BootReceiver: intent = new Intent(context, PhoneService.class); context.startService(intent); Manifest: 权限 <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 注册组件 <service android:name="com.chuanzhi.phone.PhoneService" /> <receiver android:name="com.chuanzhi.phone.BootReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
使用服务注册特殊的广播接收者
Service: @Override public void onCreate() { super.onCreate(); // 动态的注册广播 IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.SCREEN_OFF"); filter.addAction("android.intent.action.SCREEN_ON"); receiver = new ScreenReceiver(); registerReceiver(receiver, filter); } // 动态的卸载广播 @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); } Activity: //开启服务 Intent intent = new Intent(this, ScreenService.class); startService(intent);
BindService开启服务的特点
[1]通过onBind方法开启service. 只会调用onCreate和onBind方法
[2]当Activity销毁Service也会销毁
[2.0]不求同时生,但求同时死
[3]能bind服务开启的服务,在应用管理里面找不到,相当于隐形的服务
[4]当OnBind方法返回Null onServiceConnected不会执行
[5]通过Bind开启服务 不能多次解绑服务
BindService和startService的区别:
BindService随着Activity的销毁而销毁
startService不会随着Activity的销毁而销毁
为什么要引入BindService
[1]为了调用服务里面自己写的方法
通过Bindservice方式调用服务方法里面的过程
service: // [4]把自定义Binder对象返回 @Override public IBinder onBind(Intent intent) { return new myBinder(); } // [1]定义一个房子方法 如果租金大于3000就租 否则就不租 public void fangzi(int money) { if (money > 3000) { Toast.makeText(getApplicationContext(), "房子租给你", 1).show(); } else { Toast.makeText(getApplicationContext(), "这点钱租不了房子", 1).show(); } } // [2]定义一个Binder 中间人对象 public class myBinder extends Binder { // [3]自定义一个方法 调用 service里面的方法 public void zhongjie(int money) { fangzi(money); } } Manifest: <service android:name="com.chuanzhi.bind.MyService" /> Activity: // [1]通过Bind方式绑定服务 Intent intent = new Intent(this, MyService.class); myconn = new Myconn(); bindService(intent, myconn, BIND_AUTO_CREATE); class Myconn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //[2]接收服务返回的Binder对象 mBinder = (myBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { } } public void click(View v) { //[3]调用Binder里面的方法 mBinder.zhongjie(3500); } @Override protected void onDestroy() { super.onDestroy(); //[4]解绑服务 unbindService(myconn); }
通过接口方式调用服务里面的方法
接口可以隐藏代码内部的细节,只提供想提供的方法 interface: public interface IService { public void zhongjie(int money); } Service: public void chifan() { System.out.println("陪领导吃饭"); } public void guoye() { System.out.println("陪领导过夜"); } // [2]定义一个Binder 中间人对象 private class myBinder extends Binder implements IService { // [3]自定义一个方法 调用 service里面的方法 public void zhongjie(int money) { fangzi(money); } public void callchifan() { chifan(); } public void callguoye() { guoye(); } } MainActivity @Override public void onServiceConnected(ComponentName name, IBinder service) { //[2]接收服务返回的Binder对象 mBinder = (IService) service; }
百度音乐盒框架
需求:既想保证服务在后台长期运行 又想调用服务里面的方法 混合方式开启服务->先后顺序: [1]先调用start-service 保证服务在后台长期运行 [2]在调用bindservice 目的是为了调用服务里面的方法 [3]unbindservice 解绑服务 不会停止服务 [4]stopdervice 停止服务 Service: // 开始播放业务 public void startMusic() { System.out.println("开始播放 "); } // 停止播放业务 public void stopMusic() { System.out.println("停止播放"); } // 继续播放业务 public void rePlayMusic() { System.out.println("继续播放"); } //定义一个Binder对象并且实现业务接口 private class MyBinder extends Binder implements IService { @Override public void callStartMusic() { startMusic(); } @Override public void callStopMusic() { stopMusic(); } @Override public void callRePlayMusic() { rePlayMusic(); } } Activity: // 首先通过start的方式开启服务 Intent intent = new Intent(this, MusicService.class); startService(intent); // 接着绑定服务,这样就可以调用服务里面的方法了 myconn = new Myconn(); bindService(intent, myconn, BIND_AUTO_CREATE);
aidl介绍
android interface definition language :Android接口定义语言 本地服务:运行在自己应用里面的服务 远程服务:运行在其它应用里面的服务 aidl专门用来进程间通信 流程: [1]远程服务定义一个方法 [2]远程服务定义一个接口,把这个接口的.java改成.aidl,开发工具会自动生成.java文件 [3]远程定义定义Binder对象继承Stub这个类.Stub这个类是.aidl自动生成的 [4]本地服务通过隐式意图的方式 连接到远程服务 [5]本地服务在连接成功的方法里面接收远程服务传递过来的对象. [5.1]本地服务需要在自己的工程里面创建一个和远程服务同包名,同类名的.aidl文件,否则无法接收远程服务传递的对象 [6]本地服务使用Stub里面的asInterface接传递过来的Binder对象. [7]本地服役调用传递过来的Binder对象 Remote: RemoteService: //定义一个远程服务方法 public void remoteService() { System.out.println("我是远程服务里面的方法"); } //定义一个Binder对象继承Stub,Stub这个对象来自于aidl技术自动生成 private class MyBinder extends Stub { @Override public void callRemoteService() throws RemoteException { remoteService(); } } IService.aidl interface IService { void callRemoteService(); } Local: MainActivity: // 通过隐式意图连接这个服务 Intent intent = new Intent(); // 意图的Action intent.setAction("com.chuanzhi.remote"); myconn = new Myconn(); bindService(intent, myconn, BIND_AUTO_CREATE); @Override public void onServiceConnected(ComponentName name, IBinder service) { //此处是获取远程服务传递过来的对象 iservice = Stub.asInterface(service); }
aidl的应用场景
remoteService: // 支付业务 public boolean pay(String name, String pwd, int money) { if (money > 0) { return true; } else { return false; } }
补间动画
[1]透明 AlphaAnimation // 参数1:等于1时 全部显示 // 参数2:等于0时 完全透明 AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f); // 设置动画时长 aa.setDuration(2000); // 设置动画重复次数.注意这个重复次数要加上本身那一次的执行 aa.setRepeatCount(1); // 设置动画重复执行的动画的执行模式 reverse代表反转 aa.setRepeatMode(Animation.REVERSE); // 控件开启动画 img.startAnimation(aa); [2]旋转 RotateAnimation //参数1:旋转开始的角度 //参数2:旋转结束的角度 //参数3:x轴基于谁旋转 //参数4:x轴旋转的值 //参数5:y轴基于谁旋转 //参数6:y轴旋转的值 RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // 设置动画时长 ra.setDuration(2000); // 设置动画重复次数.注意这个重复次数要加上本身那一次的执行 ra.setRepeatCount(1); // 设置动画重复执行的动画的执行模式 reverse代表反转 ra.setRepeatMode(Animation.REVERSE); // 控件开启动画 img.startAnimation(ra); [3]缩放 ScaleAnimation //参数1:从x轴的哪个位置 //参数2:到x轴的哪个位置结束 //参数3:从y轴的哪个位置 //参数4:到y轴的哪个位置结束 //参数5:x轴基于谁缩放 //参数6:x轴缩放的值 //参数7:y轴基于谁缩放 //参数8:y轴缩放的值 ScaleAnimation sa = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); // 设置动画时长 sa.setDuration(2000); // 设置动画重复次数.注意这个重复次数要加上本身那一次的执行 sa.setRepeatCount(1); // 设置动画重复执行的动画的执行模式 reverse代表反转 sa.setRepeatMode(Animation.REVERSE); // 控件开启动画 img.startAnimation(sa); [4]位移 TranslateAnimation //参数1:x轴基于谁开始移动 //参数2:x轴开始移动的值 //参数3:x轴基于谁结束移动 //参数4:x轴结束移动的值 //参数5:x轴基于谁开始移动 //参数6:x轴开始移动的值 //参数7:x轴基于谁结束移动 //参数8:x轴结束移动的值 TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.2f); // 设置动画时长 ta.setDuration(2000); // 设置动画重复次数.注意这个重复次数要加上本身那一次的执行 //ta.setRepeatCount(1); // 设置动画重复执行的动画的执行模式 reverse代表反转 //ta.setRepeatMode(Animation.REVERSE); //设置动画移动后停留在移动后的位置 ta.setFillAfter(true); // 控件开启动画 img.startAnimation(ta); 注意:补间动画 都是假像。补间不会控件真实的坐标 属性动画:会改变控件的坐标。