欢迎来到皮皮网网首页

【mtk modem 源码分析】【奶茶 源码】【armminer源码】bindservice源码

来源:投诉网源码 时间:2024-11-25 03:57:20

1.JobScheduler的使用和原理
2.Android常见知识点
3.一文分析Binder机制和AIDL的理解
4.Android基础知识——四大组件
5.Android N 四大组件的工作原理

bindservice源码

JobScheduler的使用和原理

        JobScheduler主要用于在未来某个时间下满足一定条件时触发执行某项任务的情况,涉及的条件可以是网络、电量、时间等,例如执行特定的网络、是否只在充电时执行任务等。

        JobScheduler类负责将应用需要执行的任务发送给框架,以备对该应用Job的调度,是一个系统服务,可以通过如下方式获取:

        JobInfo是传递给JobScheduler类的数据容器,它封装了针对调用应用程序调度任务所需的各种约束,也可以认为一个JobInfo对象对应一个任务,JobInfo对象通过JobInfo.Builder创建。它将作为参数传递给JobScheduler:

        JobInfo.Builder是JobInfo的一个内部类,用来创建JobInfo的Builder类。

        JobService是JobScheduler最终回调的端点,JobScheduler将会回调该类中的onStartJob()开始执行异步任务。它是一个继承于JobService的抽象类,做为系统回调执行任务内容的终端,JobScheduler框架将通过bindService()方式来启动该服务。因此,用户必须在应用程序中创建一个JobService的子类,并实现其onStartJob()等回调方法,以及在AndroidManifest.xml中对它授予如下权限:

        注意在AndroidManifest.xml中添加权限

        当任务开始时会执行onStartJob(JobParameters params)方法,如果返回值是false,则系统认为这个方法返回时,任务已经执行完毕。如果返回值是true,那么系统认为这个任务正要被执行,执行任务的重担就落在了你的肩上。当任务执行完毕时你需要调用jobFinished(JobParameters params, boolean needsRescheduled)来通知系统。

        当系统接收到一个取消请求时,系统会调用onStopJob(JobParameters params)方法取消正在等待执行的任务。很重要的一点是如果onStartJob(JobParameters params)返回false,那么系统假定在接收到一个取消请求时已经没有正在运行的任务。换句话说,onStopJob(JobParameters params)在这种情况下不会被调用。

        需要注意的是这个Job Service运行在主线程,这意味着你需要使用子线程,handler,或者一个异步任务来运行耗时的操作以防止阻塞主线程。

        Google官方的Sample: /googlearchive/android-JobScheduler

        JobScheduler是一个抽象类,它在系统框架的实现类是android.app.JobSchedulerImpl

        执行的入口是JobScheduler.scheduler,其实是调了JobSchedulerImpl中的schedule方法;然后再调了mBinder.schedule(job)。这个mBinder就是JobSchedulerService,通过Binder跨进程调用JobSchedulerService。

        最后调用到JobSchedulerService中的schedule方法:

        接着发送MSG_CHECK_JOB消息,消息处理的地方是

        接着执行JobHandler中的 maybeRunPendingJobsH 方法,处理相应的任务

        availableContext是JobServiceContext,即ServiceConnection,这个是进程间通讯ServiceConnection,通过调用availableContext.executeRunnableJob(nextPending)方法,会触发调用onServiceConnected,看到这里应该明白了,onServiceConnected方法中的service就是Jobservice,里面还用了WakeLock锁,防止手机休眠。

        接着,通过Handler发消息,调用了handleServiceBoundH()方法。

        从上面源码可以看出,最终是触发调用了JobService中的startJob方法。

        从源码看,设置的内容应用于 JobStatus ,例如网络限制

        而在JobSchedulerService类,相关的状态控制在其构造函数里:

        例如网络控制类ConnectivityControllerç±»

        当网络发生改变时,会调用updateTrackedJobs(userid)方法,在updateTrackedJobs方法中,会判断网络是否有改变,有改变的会调mStateChangedListener.onControllerStateChanged()方法;然后调用了JobSchedulerService类中onControllerStateChanged方法:

        接着也是处理MSG_CHECK_JOB 消息,和上文一样,最终触发调用了JobService中的startJob方法。

        JobSchedulerService是一个系统服务,即应该在SystemServer启动的。阅读SystemServer的源码:

        run 方法如下:

        接着看 startOtherServices()

        因此,在这里就启动了JobSchedulerService服务。

        1. android 性能优化JobScheduler使用及源码分析

        2. Android 9.0 JobScheduler(一) JobScheduler的使用

        3. Android 9.0 JobScheduler(二) JobScheduler框架结构简述及JobSchedulerService的启动

        4. Android 9.0 JobScheduler(三) 从Job的创建到执行

        5. Android 9.0 JobScheduler(四) Job约束条件的控制

        6. 理解JobScheduler机制

Android常见知识点

        跳槽无非就是钱少了或不爽了,无论怎么样,记住:

        不要裸辞!

        不要裸辞!

        不要裸辞!

        为什么呢?

        1、裸辞就没有钱拿了,还不如骑驴找马。

        2、裸辞之后如果一个月内没有找到工作,那么社保就会断了,除非你自己找渠道交了。

        3、裸辞之后真的会很颓废!

        当初还在上班的时候就想着,裸辞了,首先花几天时间吧简历完善一下,把知识点恶补一下,然后投简历,面试,妥妥的妥妥。

        结果呢?每次裸辞之后都是:

        首先躺尸一个星期;

        然后用了一个星期才慢吞吞的改完简历;

        然后海投,没回复,修改简历;

        再次海投,面试,被虐得体无完肤,怀疑人生;

        再改简历,再海投,一不小心中了。

        当然海投也是有个目标范围的。

        如果不是裸辞,那么现在应该还是在公司上班,在完成工作之余,就会逼着自己复习知识点了,起码不会在家堕落。在家不上班就是睡觉、看电影,樯橹灰飞烟灭,所以不要裸辞。

        然并卵,我依然裸辞了。请假面试真的很烦。

        onPause,假如从ActivityA启动B,如果B是透明的,则不会回调A的onStop方法。

        方法一:

        方法二:

        1、写好动画文件 R.anim.enter 、 R.anim.exit

        2、调用 overridePendingTransition 设置动画

        引申:如Activity设置为singleInstance,则应该怎么设置跳转动画?

        1、startService启动方与Service并没有关联,只有当Service调用 stopSelf 或者其它组件调用 stopService 的时候服务才会终止。

        2、bindService启动方绑定Service,并且可以通过Binder与之交互,当启动方销毁时,也会自动unbindService,当所有启动方都unbindService之后,Service也就自动销毁了。

        为什么呢?官方文档是这样写的:

        大概意思是 onReceive() 执行完毕之后,它所在的进程就会变成低优先级进程,极易被系统杀死。

        分两种情况分析一下:

        一、收到广播的时候,应用正在运行:

        此时如果没有在Manifest中设置了独立进程,则 onReceive() 就直接在主进程主线程执行,这里很明显不能执行耗时操作。

        二、收到广播的时候,应用没有启动:

        这时候系统会启动一个进程去执行 onReceive() ,(如果Manifest中没有设置进程名,则进程名为包名),(插一句,所有进程都会创建一个Application实例),当onReceive执行完毕之后,此进程就变成低优先级了,随时有可能被系统杀死,如果你在onReceive里面启动了线程执行耗时任务,那很有可能子线程没执行完毕,进程就被杀死了,进程没了,线程自然就挂了。

        那么确实要执行耗时操作呢,怎么办?

        方法一:goAsync()

        方法二:schedule a JobService from the receiver using the JobScheduler

        三种实现方法

        1、继承现有的组件,如TextView等,进行拓展。

        2、继承ViewGroup,自定义布局。

        3、继承View,在onDraw()中描绘。

        onMeasure()

        onLayout()

        onDraw()

        其它

        attachToRoot 从字面理解就是是否绑定到 root 上面去了。

        1、 attachToRoot=true :则返回的view为root的子view;

        2、 attachToRoot=false :则返回的view是个单独的view,传入的root只是提供一些参数给view使用而已。

        那么这里不传入 attachToRoot 呢?那就看root是否为空了,如果传入root不为空,则默认绑定到root,作为root的子view返回。

        也就是所谓的Frame动画。指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果。

        可以通过插入器 Interpolator 控制动画的变化速度。

        也就是所谓补间动画。指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有 AlphaAnimation 、 TranslateAnimation 、 ScaleAnimation 、 RotateAnimation 四种。

        注意:只是在视图层实现了动画效果,并没有真正改变View的属性。

        属性动画,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。

        注意:Android 3.0(API )以上才支持。

        最常用的类有 ObjectAnimator

        P.S. 我不明白cancel存在的意义。

        另外, DialogFragment 是没有cancel的。

        ping

        内存大致分为三个区:栈区、堆区、方法区。

        栈区

        堆区

        方法区

        JAVA不允许手动释放内存,只能通过垃圾回收程序不定期对那些不再被引用的对象进行回收。

        那么怎么判断哪些对象需要回收?

        1、引用计数法

        就是给对象添加一个引用计数器,引用对象时+1,引用失效时-1。但是这种方法解决不了对象相互引用的情况。

        2、可达性分析法

        通过一系列“GCRoots”对象作为起点进行搜索,当GCRoots和一个对象之间没有可达路径,则认为此对象不可用,但是不可用不一定会成为可回收对象。

        编写AIDL文件,定义接口。

        编译生成JAVA文件。

        定义进程级Service,onBind中返回Interface.Stub()。

        onServiceConnected中Interface aidl = Interface.Stub.asInterface(service);

        把已修复的class文件打包成dex文件,网络传输到用户手机中,利用类加载器把这些类加载到类队列的前面即可。

        【未完待续】

        如果公司录用我,不管是三年还是五年,首先我都会先把公司的任务做好,然后不断深入研究Android的相关技术,特别是Android源码,了解Android底层原理,以便更好的优化性能,避免一些不必要的奇葩问题,还有就是研究一些新的框架的原理,学习别人的思维。最后就是学习周边语言,比如后台,前端等等。

一文分析Binder机制和AIDL的理解

       深入了解Android进程间通信机制,如同破解系统奥秘的钥匙,它在源码探索和问题解决中扮演着核心角色。Binder机制,源自OpenBinder,正是mtk modem 源码分析这个领域的主角,它弥补了Linux原生通信方式在性能和安全性的短板。它的运作涉及驱动层与应用层的无缝对接,包括与系统服务如Activity Manager Service (AMS) 的深度协作。

       Binder,作为Java编写的通信工具包,是Android多进程通信的基石。尽管AIDL(Android Interface Definition Language)常用于简化这一过程,但并非不可或缺。让我们通过一个实例,奶茶 源码不依赖AIDL,来揭示Binder通信的内在机制。想象一个简单的场景:一个客户端(ClientBinder)与服务端(ServerBinder,继承自Binder并实现onTransact方法)之间的字符串传递,透彻理解Binder通信的运作原理。

       项目框架中,服务端在Service的onBind方法中返回一个ServerBinder实例。对比手动实现与AIDL生成的代码,AIDL的便捷性便一目了然。客户端通过ServiceConnection,如下面这段代码,与远程服务建立连接:

       1. 创建ServiceConnection,获取远程服务的IBinder

       2. intent设置服务类名:"com.binder.server.RemoteService"

       3. bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)

       4. 若未连接,尝试bindService

       5. 传递数据:通过IBinder调用mStingEditText的armminer源码文本,如data.writeString(text)

       6. 成功连接后,调用transact方法传递请求

       接收数据的环节,服务端将数据展示在tvShowMessage上,通过新线程处理,如`new Handler().post(() -> ServerMainActivity.tvShowMessage.setText(message));`。当连接断开时,serviceConnection的onServiceDisconnected方法会被触发。

       关键在于客户端如何通过IBinder获取服务端对象并调用transact进行跨进程通信。AIDL的引入让这个过程更加优雅,例如在ClientMainActivityUseAidl中,服务连接成功后,通过IBinder代理mServer,调用自定义接口IShowMessageAidlInterface的showMessage方法。

       在交互过程中,value源码客户端通过IShowMessageAidlInterface的Stub内部类,将本地的IBinder转换为接口,这样数据的发送就通过showMessage方法进行。AIDL的asInterface方法负责封装本地或远程处理,Proxy类则负责数据的打包和跨进程传输,确保数据的无缝传递。

       总结来说,客户端利用AIDL的asInterface处理远程IBinder,而Proxy类则是这一切的幕后功臣。服务端的onBind方法返回AIDL生成的Stub,它在客户端调用transact时负责接收和处理请求,执行showMessage方法。这样,AIDL生成的workbook 源码Stub和Proxy成为客户端发送数据的桥梁,而在服务端,它们则是数据处理的核心所在。

       掌握Binder机制和AIDL的精髓,你将解锁Android进程间通信的无尽可能,为你的应用开发增添无限力量。无论何时,当你深入探索Android源码,这些核心原理都将是你不可或缺的指南。

Android基础知识——四大组件

       Android是一种基于Linux的自由及开放源代码的操作系统,其主要分为四个层,从上到下分别是应用程序层、应用程序框架层、系统运行库层和Linux内核层。Android系统拥有四大基本组件:Activity、Service服务、BroadcastReceiver广播接收器、Content Provider内容提供者。其中,Activity是一个应用程序组件,提供一个与用户交互的界面;Service服务为长生命周期的后台服务程序,没有可视化界面;BroadcastReceiver用于监听应用发出的广播消息,并做出响应;Content Provider作为应用程序之间共享数据的途径,提供统一接口用于存储和读取数据。

       Activity介绍:Activity是一个负责与用户交互的组件,显示在屏幕上的每一个界面都是一个Activity实例。Activity可以监听并处理用户的事件做出响应,并且可以显示一些控件。所有操作都与用户密切相关。Activity之间通过Intent进行通信。Activity有四种基本状态:Active/Running(激活状态或运行状态)、Paused(暂停状态)、Stopped(停止状态)、Killed(销毁状态)。当一个Activity实例被创建、销毁或者启动另一个Activity时,它会在这四种状态之间进行转换。Activity栈通过管理Activity实例的状态来控制它们在屏幕上的显示顺序。

       Service介绍:Service是运行于后台,没有可视化界面的一种服务程序。它可以通过两种方式启动:Started Service(通过其他组件调用startService()创建,可以无限运行,需要调用stopSelf()或stopService()停止)和Bounded Service(通过其他组件调用bindService()创建,可以与多个组件进行通信,当所有绑定组件解除后,系统会销毁Service)。

       BroadcastReceiver介绍:BroadcastReceiver是监听应用发出的广播消息,并做出响应的组件。它可以用于不同组件之间通信、与Android系统通信等场景。Android广播使用观察者模式实现,基于消息的发布/订阅事件模型。注册BroadcastReceiver有静态注册和动态注册两种方式。静态注册在AndroidManifest.xml中声明,常驻注册不受组件生命周期影响;动态注册在代码中通过Context的registerReceiver()方法进行,需要在组件生命周期结束时注销。

       Content Provider介绍:Content Provider是Android应用程序组件之一,作为应用程序之间共享数据的途径,提供统一接口用于存储和检索数据。Content Provider主要功能是存储、检索数据以及向其他应用程序提供访问数据的接口。Android系统内置了多个Content Provider用于管理不同数据类型,如音乐、视频、图像、联系人信息等。访问Content Provider中的数据主要通过ContentResolver对象,支持查询、插入、修改、删除操作。实现Content Provider需要定义CONTENT_URI常量、继承Content Provider类、实现相关方法,并在AndroidManifest.xml中声明。

Android N 四大组件的工作原理

       æœ¬æ–‡ä¾§é‡è®²è§£android N 系统中四大组件的工作原理,不同系统原理略有差别。通过分析四大组件的工作流程加深对Android Framework的理解,也为插件化开发打下基础。

        Activity

        展示一个界面并和用户交互,它扮演的是一个前台界面的角色。

        Service

        计算型组件,用于后台执行一系列计算任务,工作在主线程,耗时操作需要另起线程, 分为启动状态和绑定状态。

        BroadcastReceiver

        消息型组件,主要用于不同组件或者不同应用之间的消息传递,它工作在系统内部,不适合执行耗时操作,操作超过5s,会出现ANR。

        ContentProvider

        数据共享型组件,用于向其他组件或者应用共享数据,主要执行CURD操作。

        我们启动一个activity有两种方法,

        第一种(Activity直接启动方式):

        Intent intent = new Intent(this, MainActivity.class);

        startActivity(intent);

        第二种(Context启动方式)

        Intent intent = new Intent(this, MainActivity.class);

        getApplicationContext().startActivity(intent);

        不同的启动方式Activity的工作流程有点差别。

        两种启动都会调用到Instrumentation类中的execStartActivity的方法,系统最终是通过ActivityThread中的performLaunchActivity完成Activity的创建和启动。

        performLaunchActivity方法主要完成以下工作:

        1、通过ActivityClientRecord对象获取启动activity的组件信息

        2、通过mInstrumentation对象的newActivity方法调用classloader完成activity的创建

        3、通过r.packageInfo(LoadedApk 对象)的makeApplication方法尝试创建Application对象

        4、创建ContextImpl对象并调用Activity的attach方法完成一些数据的初始化

        5、调用Activity的onCreate方法

        在Activity启动的过程中,App进程会频繁地与AMS进程进行通信:

        App进程会委托AMS进程完成Activity生命周期的管理以及任务栈的管理;这个通信过程AMS是Server端,App进程通过持有AMS的client代理IActivityManager完成通信过程;

        AMS进程完成生命周期管理以及任务栈管理后,会把控制权交给App进程,让App进程完成Activity类对象的创建,以及生命周期回调;这个通信过程也是通过Binder完成的,App所在server端的Binder对象存在于ActivityThread的内部类ApplicationThread;AMS所在client通过持有IApplicationThread的代理对象完成对于App进程的通信。

        Service有两种启动方式,startService()和bindService(),两种状态可以并存:

        startService流程

        bindService流程

        BroadcastReceiver的工作过程主要包括广播的注册、发送和接收:

        动态注册过程:

        发送过程

        静态注册是由PackageManagerService(PMS)在应用安装的时候完成整个注册过程的,除广播以外,其他三大组件也都是在应用安装时由PMS解析并注册的。

        每个进程的入口都是ActivityThead.main(),App的启动流程如下:

        从源码中可以看出:

        应用启动的入口为ActivityThread的main方法,main方法会创建ActivityThread实例并创建主线程消息队列。

        attach方法中远程调用AMS的attachApplication方法,并提供ApplicationThread用于和AMS的通信。

        attachApplication方法会通过bindApplication方法和H来调回ActivityThread的handleBindApplication,这个方法会先创建Application,再加载ContentProvider,然后才会回调Application的onCreate方法。

        由上图可以看出,在ContentProvider的启动过程中伴随着app进程的启动。

        ContentProvider的其他CURD操作如insert,delete,update跟query的流程类似。