1.进程概念
进程代表不同应用程序,系统会为每个应用程序创建一个进程和线程(主线程)
进程分类
1.前台进程
Foreground process
:用户正在交互 ,当广播接收者的onReceive方法执行
2.可视进程
Visible process
用户不可以交互 但是可以看得见
3.服务进程
Service process 进程里面运行了一个服务 (音乐播放器)
4.后台进程
Background process
用户看不见 相当于activity执行了onStop方法
5.空进程
Empty process
不会立刻杀死 目的是为了 下一次打开速度.
2.服务的入门
服务是在后台运行.和windos下服务类似 activity你大爷--->Service.
startservice特点
1.第一次启动服务 服务会执行onCreate和onStart方法
2.当第二次在点击按钮开启服务 服务只会执行onStrat方法 服务一旦开启就会在后台长期运行,直到用户手动停止.
3.电话监听器
代码实现步骤
1.开启一个服务 服务在后台监听电话的状态
public class PhoneService extends Service {
public PhoneService() {
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
//当服务第一次创建的时候执行 监听电话的状态
@Override
public void onCreate() {
//1.通过查看文档得知 使用getSystemService方法获取实例
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
//2.监听电话的状态
tm.listen(new MyPhoneStateListener(),PhoneStateListener.LISTEN_CALL_STATE);
super.onCreate();
}
//定义电话监听类 为什么要继承
class MyPhoneStateListener extends PhoneStateListener{
//当设备的状态发生改变的时候执行 state代表电话的状态
@Override
public void onCallStateChanged(int state, String incomingNumber) {
//1.判断电话状态
switch (state){
case TelephonyManager.CALL_STATE_IDLE: //空闲状态
break;
case TelephonyManager.CALL_STATE_OFFHOOK://摘机 接听状态
System.out.println("开始录");
break;
case TelephonyManager.CALL_STATE_RINGING: //响铃状态
System.out.println("准备录音机");
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
}
2.具体实现录音功能
{
//1.判断电话状态
switch (state){
case TelephonyManager.CALL_STATE_IDLE: //空闲状态
if (recorder!=null){
recorder.stop(); //停止录
recorder.reset();
recorder.release();
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK://摘机 接听状态
recorder.start();
System.out.println("开始录");
break;
case TelephonyManager.CALL_STATE_RINGING: //响铃状态
System.out.println("准备录音机");
//1.创建MediaRecorder实例
recorder = new MediaRecorder();
//2.设置音频的来源 mic 麦克风
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//3.设置输出文件文件 3gp mp4 avi
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
//4.设置音频编码方式
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
//5.指定文件存储路径
recorder.setOutputFile(getFilesDir().getPath()+"/"+"luyin.3gp");
//6.准备录
try {
recorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
super.onCallStateChanged(state, incomingNumber);
}
3.添加对应权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_PHONE_STATE">uses-permission>
4.注册特殊广播接收者.
public class ScreenService extends Service {
private ScreenReceiver screenReceiver;
public ScreenService() {
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
//1.获取ScreenReceiver的实例
screenReceiver = new ScreenReceiver();
//2.构造意图过滤器类
IntentFilter intentFilter = new IntentFilter();
//3.添加action
intentFilter.addAction("android.intent.action.SCREEN_OFF");
intentFilter.addAction("android.intent.action.SCREEN_ON");
//4 .动态去注册广播接收者
registerReceiver(screenReceiver,intentFilter);
super.onCreate();
}
@Override
public void onDestroy() {
//当服务销毁的时候取消注册广播接收者
unregisterReceiver(screenReceiver);
super.onDestroy();
}
}
5.bindservice开启服务特点
bindservice开启服务在后台找不到.相当于开启了一个隐形的服务.更牛一些. 第一次开启服务会执行onCreate方法和onBind方法.
当activity销毁的时候 服务也会跟着销毁. 天龙八部-->乔峰 虚竹 段誉 不求同生 但求同死.
为什么要引入bindservice:目的就是为了调用服务里面的方法.
6.bindservice调用服务流程:
1.在服务内部有一个方法需要我们调用 比如办证方法
public void banZheng(int money){
if (money > 500){
Toast.makeText(this,"我了是领导,把证给你办了",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this,"这点钱 还想办事",Toast.LENGTH_LONG).show();
}
}
2.在服务内部 声明一个中间人对象(IBinder实现类)
//1.在服务内部定义一个中间人对象 小舅子 (实际上就是IBinder类的实现类)
class Mybinder extends Binder{
//2.这个类的内部定义一个方法 调用办证的方法
public void callBanzZheng(int money){
banZheng(money);
}
}
3.在服务的onBind方法里面把我们定义的中间人对象返回
//2.在这个方法把我们定义的中间人对象返回
@Override
public IBinder onBind(Intent intent) {
return new Mybinder();
}
4.在mainActivity里面调用bindService 目的是为了获取我们定义的中间人对象
public class MainActivity extends AppCompatActivity {
private BanZhengService.Mybinder mybinder; //就是我们定义的中间人对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.创建意图
Intent intent = new Intent(this, BanZhengService.class);
//2.创建conn对象
MyConn myConn = new MyConn();
//3.连接服务
bindService(intent,myConn,BIND_AUTO_CREATE);
}
//点击按钮 调用服务的办证方法
public void click(View view) {
mybinder.callBanzZheng(3);
}
//监视服务的状态
class MyConn implements ServiceConnection{
//当连接成功
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//在这个方法里面获取我们定义的中间人对象实例
mybinder = (BanZhengService.Mybinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
7.使用接口方式调用服务里面的方法
接口好处:接口可以隐藏代码内部细节,让程序员暴漏自己想暴漏的方法.
代码实现步骤
1.定义一个接口 把想暴漏的方法定义在接口里
2.在获取中间人对象的方式上发生了变化
8.混合开启服务--->百度音乐盒
既想保证服务在后台长期运行,又想调用服务里面的方法,使用哪个方式开启服务.
//混合方式开启服务的流程
//1.为了提升进程优先级 保证服务在后台长期运行
Intent intent = new Intent(this,MusicService.class);
startService(intent);
//2.通过调用bindservice 来获取我们定义的中间人对象
bindService(intent,new Myconn(),BIND_AUTO_CREATE);
9.远程服务和本地服务
远程服务: 运行在其他应用里面服务
本地服务: 运作在自己应用的服务
10.aidl
aidl是什么 aidl:android interface definition language android接口定义语言
aidl 有什么用 aidl专门用来解决进程间通信(IPC)
aidl 怎么用
实现步骤
1.直接main目录下创建一个aidl文件 点击同步按钮 让系统帮助我们生成一个iservice.java文件
2.在iservice.java文件里面系统会自动生成一个stub类 stub类默认继承binder并且实现了iservice接口
3.把我们定义的中间人对象继承Stub
4.直接把aidl文件拷贝到另外一个应用程序 点击同步按钮 直接也会生成iservice文件
5.获取中间人对象的方式不一样了
iservice = Iservice.Stub.asInterface(service);
关于面试的问题:
你了解ipc么 如何实现ipc: aidl
你用过aidl么,ipc.
11.aidl应用场景
新浪:微博 通过aidl接口对外暴漏数据 api开发接口. 天气应用:墨迹天气
支付宝暴漏支付接口 ,斗地主买豆.
12.补间动画
//点击按钮实现 透明动画效果
public void click1(View view) {
//创建一个透明动画实例 参数1:代表开始透明值 1.0代表完全不透明 0.0完全透明
AlphaAnimation aa = new AlphaAnimation(1.0f,0.0f);
//设置动画执行时长
aa.setDuration(2000);
//设置动画重复次数
aa.setRepeatCount(1);
//设置动画执行重复的模式
aa.setRepeatMode(Animation.REVERSE);
//让iv执行动画
iv.startAnimation(aa);
}
//点击按钮 实现旋转动画
public void click2(View view){
//参数3和参数4 决定了小机器人X轴旋转的位置:控件真实位置 0.5 代表控件宽*0.5
RotateAnimation ra = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
//设置动画执行时长
ra.setDuration(2000);
//设置动画重复次数
ra.setRepeatCount(1);
//设置动画执行重复的模式
ra.setRepeatMode(Animation.REVERSE);
//让iv执行动画
iv.startAnimation(ra);
}
//点击按钮 实现缩放(放大和缩小)动画
public void click3(View view) {
//参数1 1.0f代表默认值
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);
//设置动画执行重复的模式
sa.setRepeatMode(Animation.REVERSE);
//让iv执行动画
iv.startAnimation(sa);
}
//点击按钮实现位移效果
public void click4(View view) {
//想实现位移 不能相对自己 0.2 :代表相对布局高度*0.2 慎用整数
TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT,0.0f,Animation.RELATIVE_TO_PARENT,0.0f,
Animation.RELATIVE_TO_PARENT,0.0f,Animation.RELATIVE_TO_PARENT,0.2f);
//设置动画执行时长
ta.setDuration(2000);
//让动画执行完 停留在介绍的位置上
ta.setFillAfter(true);
//让iv执行动画
iv.startAnimation(ta);
}
总结 补间动画原理: 不会改变控件真实的坐标,只是产生了一个动画效果而已.