精华内容
下载资源
问答
  • Android框架揭秘.pdf

    千次下载 热门讨论 2013-05-13 17:30:39
    Android框架揭秘.pdf 老外写的,看看那
  • Android 框架 与 源码结构



    一. Android 框架


    Android框架层级 : Android 自下 而 上 分为 4层;

    -- Linux内核层;

    -- 各种库 和 Android运行环境层;

    -- 应用框架层;

    -- 应用层;


    1. Linux内核层


    Android 的 Linux 内核层 组成 : Linux 内核驱动程序;


    Linux内核 : Android 2.x 是基于 Linux 2.6 内核;


    驱动程序

    -- Display Driver (显卡驱动) : Linux 的帧缓冲 驱动;

    -- Flash Memory Driver (Flash 内存驱动) : 基于 MTD 的 Flash 驱动程序;

    -- Camera Driver (相机驱动) : 基于 Linux v4l 驱动;

    -- Audio Driver (音频驱动) : 基于 ALSA 驱动;

    -- Wifi Driver (Wifi驱动) : 基于 IEEE 801.31 标准的驱动程序;

    -- KeyBoard Driver (键盘驱动) : 作为输入设备的键盘驱动;

    -- Bluetooth Driver (蓝牙驱动) : 基于 IEEE 801.35.1 标准的无线传输技术;

    -- Binder IPC Driver : Android 特有的驱动程序, 有单独的设备节点, 提供进程通信的功能;

    -- Power Management (电源管理) : 管理电池电量等信息;


    解析驱动

    -- Frame Buffer (帧缓冲) : 视频输出设备 中包含 有 完整帧数据的 视频缓冲区, 使用该缓冲区 驱动视频显示设备;

    -- v4l (Video for linux) : Linux 中的 摄像头驱动;

    -- ALSA (Advanced Linux Sound Architecture) : 高级 Linux 声音体系驱动, 该组件 提供了 声卡驱动;



    2. 库 和 Android 运行环境


    该层分两部分 : Android 运行环境 和 各种 库;


    各种库介绍 : 这些库以系统中间件形式提供, 与移动设备平台的应用有密切的关系;

    -- C标准库 : Android 系统最底层的库, 该标准库调用 内核的系统调用实现所需的功能;

    -- Media Framework (多媒体框架) : Android 多媒体核心部分, 是基于 PacketVideo 的 OpenCore框架, 功能一 音频视频回放, 功能二 音频视频记录;

    -- SGL : 2D的引擎;

    -- SSL (Secure Socket Layer) : 主要 为 TCP/IP 协议 与 应用层协议 之间的数据通信 提供安全支持;

    -- OpenGL ES : 3D引擎;

    -- Surface Management (界面管理工具) : 管理显示子系统的功能;

    -- SQLite : 嵌入式数据库;

    -- WebKit : 网络浏览器内核;

    -- FreeType : 提供位图 和 矢量字体功能;


    Dalvik虚拟机 与 JVM 区别

    -- 执行文件 : JVM 执行 .class 标准字节码文件, Dalvik 虚拟机执行 .dex 文件;

    -- 最大区别 : JVM 是基于栈 (Stack-based) 的虚拟机, Dalvik 虚拟机 是基于寄存器 (Register-based) 的虚拟机, 后者可以根据硬件实现更好的优化; 



    3. 应用程序框架层


    应用框架层 : 该层 提供了 应用程序使用的 API, 包括 各种 UI 组件 和 其它组件, 包括下面的组件;

    -- Activity : 主要活动界面;

    -- BroadcastReceiver : 广播接收者;

    -- Service : 服务;

    -- ContentProvider : 内容提供者;


    4. 应用程序层


    该层主要是 apk 安装程序;




    二. Android 源码结构 


    基于 android-2.3.4_r1 版本的源码进行分析;


    Android 源码结构分类

    -- 核心部分 : 该部分是建立Android 系统的基础, 被保存在根目录的文件中;

    -- 扩展工程 : 使用其它开源项目的部分;

    -- 包部分 : 提供了 Android 应用程序, 四大组件 等, 在 package 目录中;



    1. 根目录 (/)


    bionic : 基础库的源码, C 运行时支持库 libc, libm, libdl, 动态 linker;

    bootable/bootloader/legacy : 内核引导加载器, 加载内核之前运行的程序;

    build : 编译和配置所需要的脚本 和 工具;

    dalvik : Android中的 Java 虚拟机, 提供Android应用程序运行基础;

    development : 程序开发所需的模板和工具, 层次较高;

    external : 使用的其它的开源的扩展库;

    frameworks : 应用程序框架层, 四大组件等;

    hardware : 硬件相关的库;

    kernel : Linux 内核源码;

    packages : Android 各种应用程序;

    prebuilt : 各种平台下的编译预置脚本;

    recovery : 与 Android 系统恢复功能相关;

    system : Android 底层库;

    Makefile : 整个 Android 源码 编译的 Makefile;


    2. development 目录 (/development)


    apps : Android 应用程序模板;

    build : 编译脚本模板;

    host : windows 平台的一些工具;

    samples : 示例程序, 简单的Android程序, 可以作为模板;


    3. external 目录 (/external)


    opencore : Android 多媒体框架核心;

    webkit : Android 网络浏览器核心;

    sqlite : Android 数据库系统核心;

    openssl : Secure Socket Layer, 是一个网络协议, 为数据通信提供安全支持;


    4. frameworks


    base : Android 核心框架库基本内容;

    opt : 可选部分;


    base 目录内容

    -- cmds : 重要的命令;

    -- core : 核心库;

    -- data : 字体声音数据文件;

    -- docs : 文档;

    -- graphics : 图形相关;

    -- include : 头文件;

    -- keystore : 数据签名证书;

    -- libs : 库;

    -- location : 地区库;

    -- media : 媒体相关库;

    -- obex : 蓝牙相关的库;

    -- opengl : 3D图形库;

    -- packages : 设置 TTS VPN 等库;

    -- sax : XML 解析;

    -- services : 各种服务;

    -- telephony : 电话通信管理;

    -- test-runner : 测试工具相关;

    -- test : 各种测试;

    -- tools : 各种工具;

    -- vpn

    -- wifi



    5. packages 目录 (/packages)


    Apps : Android 中的各种应用程序;

    providers : 保存内容提供者信息;

    inputmethod : 输入法;

    wallpapers : 墙纸;


    展开全文
  • Android框架之路——聊天Demo实现

    万次阅读 2017-05-07 10:54:02
    一、所用技术 GreenDao存储聊天数据;...Android框架之路——GreenDao3.2.2的使用 Android框架之路——RecyclerView的使用 Android框架之路——ButterKnife的使用 二、实现效果后台每5s发送数据过

    一、所用技术

    • GreenDao存储聊天数据;
    • RecyclerView根据viewtype显示聊天界面;
    • butterknife绑定view;

       如果这些你还没有了解,你可以参考这些文章:

    二、实现效果

    后台每5s发送数据过来,存储到数据库中,并显示到界面上,用户可以发送文字,保存到数据库并显示。.9的图片比较丑,缺一个美工姑娘,欢迎联系。。。

    Center

    三、总体思路

    通过RecyclerView的viewType来决定加载左右聊天布局,通过greendao来操作数据库。一些细节问题较多,需要逐个解决。

    1. 编写activity_main.xml,主要由一个RecyclerView和下方的EditText输入框以及发送按钮组成。

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout
          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:background="@android:color/white"
          android:padding="5dp"
          tools:context="com.ping.chatdemo.activity.MainActivity">
      
          <android.support.v7.widget.RecyclerView
              android:id="@+id/rv_chatList"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_above="@+id/linearLayout">
      
          </android.support.v7.widget.RecyclerView>
      
          <LinearLayout
              android:layout_alignParentBottom="true"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:id="@+id/linearLayout">
              <android.support.design.widget.TextInputLayout
                  android:layout_width="0dp"
                  android:layout_weight="6"
                  android:layout_height="50dp">
                  <EditText
                      android:id="@+id/et_content"
                      android:hint="请输入文字..."
                      android:textSize="15dp"
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"/>
              </android.support.design.widget.TextInputLayout>
      
              <Button
                  android:id="@+id/bt_send"
                  android:padding="10dp"
                  android:textSize="15dp"
                  android:text="发送"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"/>
          </LinearLayout>
      
      </RelativeLayout>
      
    2. 看一下我们的聊天布局,分为左右俩个布局文件,一个TextView显示当前时间,然后就是聊天头像与内容;
      左布局:

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@android:color/white"
                    android:orientation="vertical"
                    android:paddingBottom="5dp"
                    android:paddingLeft="12dp"
                    android:paddingRight="12dp"
                    android:paddingTop="3dp">
      
          <TextView
              android:id="@+id/tv_left_time"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center_horizontal"
              android:text="2015-6-6 06:06:06"/>
      
          <RelativeLayout
              android:layout_marginTop="2dp"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
      
              <ImageView
                  android:id="@+id/img_ble"
                  android:layout_width="40dp"
                  android:layout_height="40dp"
                  android:layout_alignParentLeft="true"
                  android:layout_marginRight="4dp"
                  android:src="@drawable/ic_ble"/>
      
              <TextView
                  android:id="@+id/tv_msg_left"
                  android:layout_width="wrap_content"
                  android:layout_height="40dp"
                  android:textSize="13dp"
                  android:layout_marginRight="50dp"
                  android:background="@drawable/imageleft"
                  android:layout_toRightOf="@id/img_ble"
                  android:textColor="@android:color/white"/>
          </RelativeLayout>
      </LinearLayout>
      

      右布局:

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:background="@android:color/white"
                      android:orientation="vertical"
                      android:paddingBottom="5dp"
                      android:paddingLeft="12dp"
                      android:paddingRight="12dp"
                      android:paddingTop="3dp">
      
          <TextView
              android:id="@+id/tv_right_time"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center_horizontal"
              android:text="2015-6-6 06:06:06"/>
      
          <RelativeLayout
              android:layout_marginTop="2dp"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
      
              <ImageView
                  android:id="@+id/img_phone"
                  android:layout_width="40dp"
                  android:layout_height="40dp"
                  android:layout_alignParentRight="true"
                  android:layout_marginLeft="4dp"
                  android:src="@drawable/ic_phone"/>
      
              <TextView
                  android:id="@+id/tv_msg_right"
                  android:layout_width="wrap_content"
                  android:layout_height="40dp"
                  android:textSize="13dp"
                  android:layout_marginLeft="50dp"
                  android:background="@drawable/imageright"
                  android:layout_toLeftOf="@id/img_phone"
                  android:textColor="@android:color/black"/>
      
          </RelativeLayout>
      
      
      </LinearLayout>
      
    3. 看一下我们的Msg.java聊天实体,里面包含了主键_id,聊天时间,聊天内容和聊天布局类型,此类方法是通过greendao注解生成的;

      @Entity
      public class Msg {
      
          public static final int TYPE_BLE = 0;
          public static final int TYPE_PHONE = 1;
      
          @Id(autoincrement = true)
          private Long _id;
          @NotNull
          private String content;
          @NotNull
          private int type;
          @NotNull
          private String time;
          @Generated(hash = 1787798591)
          public Msg(Long _id, @NotNull String content, int type, @NotNull String time) {
              this._id = _id;
              this.content = content;
              this.type = type;
              this.time = time;
          }
          @Generated(hash = 23037457)
          public Msg() {
          }
          public Long get_id() {
              return this._id;
          }
          public void set_id(long _id) {
              this._id = _id;
          }
          public String getContent() {
              return this.content;
          }
          public void setContent(String content) {
              this.content = content;
          }
          public int getType() {
              return this.type;
          }
          public void setType(int type) {
              this.type = type;
          }
          public String getTime() {
              return this.time;
          }
          public void setTime(String time) {
              this.time = time;
          }
      
          @Override
          public String toString() {
              return "Msg{" +
                      "_id=" + _id +
                      ", content='" + content + '\'' +
                      ", type=" + type +
                      ", time='" + time + '\'' +
                      '}';
          }
          public void set_id(Long _id) {
              this._id = _id;
          }
      }
      
    4. 接下来我们要着手编写聊天的Apater了,在Adapter中我们需要根据Msg的viewType来返回不同的holder,即渲染不同的视图。下面就是我们ChatAdapter的具体实现;

      public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
      
          private LayoutInflater mLayoutInflater;
          private Context mContext;
          private List<Msg> mDatas;
      
          public ChatAdapter(Context context, List<Msg> datas) {
              mContext = context;
              mLayoutInflater = LayoutInflater.from(mContext);
              mDatas = datas;
          }
      
          //添加消息显示在RecyclerView中
          public void addItem(Msg msg) {
              mDatas.add(msg);
              notifyDataSetChanged();
          }
      
          @Override
          public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
              if (viewType == Msg.TYPE_BLE) {
                  View view = mLayoutInflater.inflate(R.layout.item_chat_left, parent, false);
                  return new ChatLeftViewHolder(view);
              } else {
                  View view = mLayoutInflater.inflate(R.layout.item_chat_right, parent, false);
                  return new ChatRightViewHolder(view);
              }
          }
      
          @Override
          public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
              Msg msg = mDatas.get(position);
              String time = msg.getTime();
              String content = msg.getContent();
              if(holder instanceof ChatLeftViewHolder){
                  ((ChatLeftViewHolder) holder).mTvLeftTime.setText(time);
                  ((ChatLeftViewHolder) holder).mTvMsgLeft.setText(content);
              }else if(holder instanceof ChatRightViewHolder){
                  ((ChatRightViewHolder) holder).mTvRightTime.setText(time);
                  ((ChatRightViewHolder) holder).mTvMsgRight.setText(content);
              }
          }
      
          @Override
          public int getItemViewType(int position) {
              return mDatas.get(position).getType();
          }
      
          @Override
          public int getItemCount() {
              return mDatas.size();
          }
      
          static class ChatLeftViewHolder extends RecyclerView.ViewHolder {
              @BindView(R.id.tv_left_time)
              TextView mTvLeftTime;
              @BindView(R.id.tv_msg_left)
              TextView mTvMsgLeft;
      
              ChatLeftViewHolder(View view) {
                  super(view);
                  ButterKnife.bind(this, view);
              }
          }
      
          static class ChatRightViewHolder extends RecyclerView.ViewHolder{
              @BindView(R.id.tv_right_time)
              TextView mTvRightTime;
              @BindView(R.id.tv_msg_right)
              TextView mTvMsgRight;
      
              ChatRightViewHolder(View view) {
                  super(view);
                  ButterKnife.bind(this, view);
              }
          }
      }
      
    5. 编写完上述的一些关于界面显示的东西后,我们要来继续完成我们的数据库操作方法,和这篇教程一样,我们需要单例模式来封装一个DaoManager类,基本不怎么变化,变化的是我们Util,我们针对这次的Msg实体编写MsgDaoUtil类如下。这里我们还给其注入了一个监听器,用来监听是否数据库进行数据插入操作了;

      public class MsgDaoUtil {
          private static final String TAG = MsgDaoUtil.class.getSimpleName();
          private DaoManager mManager;
          private OnDbUpdateListener mUpdateListener;
      
          public void setUpdateListener(OnDbUpdateListener updateListener) {
              mUpdateListener = updateListener;
          }
      
          public MsgDaoUtil(Context context){
              mManager = DaoManager.getInstance();
              mManager.init(context);
          }
      
          /**
           * 完成msg记录的插入,如果表未创建,先创建Msg表
           * @param msg
           * @return
           */
          public boolean insertMsg(Msg msg){
              boolean flag = false;
              flag = mManager.getDaoSession().getMsgDao().insert(msg) == -1 ? false : true;
              if(flag)
                  mUpdateListener.onUpdate(msg);
              Log.i(TAG, "insert Msg :" + flag + "-->" + msg.toString());
              return flag;
          }
      
          /**
           * 查询所有记录
           * @return
           */
          public List<Msg> queryAllMsg(){
              return mManager.getDaoSession().loadAll(Msg.class);
          }
      }
      
    6. 最后就是在MainActivity.java中完成我们的业务逻辑了。这里面有几个细节问题,一个是打开页面加载出数据库里的聊天记录,另一个是当下滑RecyclerView时需要隐藏软键盘,还有一个要监听数据库的插入操作,当然,RecyclerView布满时,来记录后要自动上滑,显示最新消息。

      public class MainActivity extends AppCompatActivity {
      
          private List<Msg> mMsgs;
          private MsgDaoUtil mMsgDaoUtil;
          private ChatAdapter mAdapter;
          SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      
          @BindView(R.id.rv_chatList)
          RecyclerView mRvChatList;
          @BindView(R.id.et_content)
          EditText mEtContent;
          @BindView(R.id.bt_send)
          Button mBtSend;
      
          //后台定时5s发送数据
          Handler handler = new Handler();
          Runnable runnable = new Runnable() {
              @Override
              public void run() {
                  // TODO Auto-generated method stub
                  addMsg(new Msg(null, "来数据了!", Msg.TYPE_BLE, df.format(new Date())));
                  handler.postDelayed(this, 5000);
              }
          };
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              ButterKnife.bind(this);
      
              mMsgDaoUtil = new MsgDaoUtil(this);
              //加载历史聊天记录
              mMsgs = mMsgDaoUtil.queryAllMsg();
      
              LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
              mRvChatList.setLayoutManager(linearLayoutManager);
              mAdapter = new ChatAdapter(this, mMsgs);
              mRvChatList.setAdapter(mAdapter);
              //初试加载历史记录呈现最新消息
              mRvChatList.scrollToPosition(mAdapter.getItemCount() - 1);
      
              mMsgDaoUtil.setUpdateListener(new OnDbUpdateListener() {
                  @Override
                  public void onUpdate(Msg msg) {
                      mAdapter.addItem(msg);
                      //铺满屏幕后呈现最新消息
                      mRvChatList.scrollToPosition(mAdapter.getItemCount() - 1);
                  }
              });
      
              //设置下滑隐藏软键盘
              mRvChatList.addOnScrollListener(new RecyclerView.OnScrollListener() {
                  @Override
                  public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                      super.onScrolled(recyclerView, dx, dy);
                      if (dy < -10) {
                          InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                          imm.hideSoftInputFromWindow(mEtContent.getWindowToken(), 0);
                      }
                  }
              });
      
              handler.postDelayed(runnable, 5000);
          }
      
          private boolean addMsg(Msg msg) {
              return  mMsgDaoUtil.insertMsg(msg);
          }
      
      
          @OnClick(R.id.bt_send)
          public void onViewClicked() {
              String content = mEtContent.getText().toString();
              addMsg(new Msg(null, content, Msg.TYPE_PHONE, df.format(new Date())));
              mEtContent.setText("");
          }
      }
      

    四、Demo下载

       源码链接



    个人公众号:每日推荐一篇技术博客,坚持每日进步一丢丢…欢迎关注,想建个微信群,主要讨论安卓和Java语言,一起打基础、用框架、学设计模式,菜鸡变菜鸟,菜鸟再起飞,愿意一起努力的话可以公众号留言,谢谢…

    20170530210352492

    展开全文
  • Android框架揭秘电子书pdf下载

    千次阅读 2019-01-04 00:06:58
    Android框架揭秘下载链接: https://pan.baidu.com/s/1W1xrsC2-w5MgsrY-6i_cFg 提取码获取方式:关注下面微信公众号,回复关键字: 1119

    Android框架揭秘下载链接:

    https://pan.baidu.com/s/1W1xrsC2-w5MgsrY-6i_cFg

    提取码获取方式:关注下面微信公众号,回复关键字: 1119

    展开全文
  • 第四章 Android 框架层安全 来源:Yury Zhauniarovich | Publications 译者:飞龙 协议:CC BY-NC-SA 4.0 如我们在第1.2节中所描述的那样,应用程序框架级别上的安全性由 IPC 引用监视器实现。 在 4.1 节中,...

    第四章 Android 框架层安全

    来源:Yury Zhauniarovich | Publications

    译者:飞龙

    协议:CC BY-NC-SA 4.0

    如我们在第1.2节中所描述的那样,应用程序框架级别上的安全性由 IPC 引用监视器实现。 在 4.1 节中,我们以 Android 中使用的进程间通信系统的描述开始,讲解这个级别上的安全机制。 之后,我们在 4.2 节中引入权限,而在 4.3 节中,我们描述了在此级别上实现的权限实施系统。

    4.1 Android Binder 框架

    如 2.1 节所述,所有 Android 应用程序都在应用程序沙箱中运行。粗略地说,应用程序的沙箱通过在带有不同 Linux 身份的不同进程中运行所有应用程序来保证。此外,系统服务也在具有更多特权身份的单独进程中运行,允许它们使用 Linux Kernel DAC 功能,访问受保护的系统不同部分(参见第 2.1, 2.2 和 1.2 节)。因此,需要进程间通信(IPC)框架来管理不同进程之间的数据和信号交换。在 Android 中,一个称为 Binder 的特殊框架用于进程间通信[12]。标准的 Posix System V IPC 框架不支持由 Android 实现的 Bionic libc 库(参见[这里](https://android.googlesource.com/platform/ndk/+/android-4.2.2_r1.2/docs/system/ libc/SYSV-IPC.html))。此外,除了用于一些特殊情况的 Binder 框架,也会使用 Unix 域套接字(例如,用于与 Zygote 守护进程的通信),但是这些机制不在本文的考虑范围之内。

    Binder 框架被特地重新开发来在 Android 中使用。 它提供了管理此操作系统中的进程之间的所有类型的通信所需的功能。 基本上,甚至应用程序开发人员熟知的机制,例如IntentsContentProvider,都建立在 Binder 框架之上。 这个框架提供了多种功能,例如可以调用远程对象上的方法,就像本地对象那样,以及同步和异步方法调用,Link to Death(某个进程的 Binder 终止时的自动通知),跨进程发送文件描述符的能力等等[12,16] 。

    根据由客户端 - 服务器同步模型组织的进程之间的通信。客户端发起连接并等待来自服务端的回复。 因此,客户端和服务器之间的通信可以被想象为在相同的进程线程中执行。 这为开发人员提供了调用远程对象上的方法的可能性,就像它们是本地的一样。 通过 Binder 的通信模型如图 4.1 所示。 在这个图中,客户端进程 A 中的应用程序想要使用进程 B [12]中运行的服务的公开行为。

    使用 Binder 框架的客户端和服务之间的所有通信,都通过 Linux 内核驱动程序/dev/binder进行。此设备驱动程序的权限设置为全局可读和可写(见 3.1 节中的清单 3.3 中的第 3 行)。因此,任何应用程序可以写入和读取此设备。为了隐藏 Binder 通信协议的特性,libbinder库在 Android 中使用。它提供了一种功能,使内核驱动程序的交互过程对应用程序开发人员透明。尤其是,客户端和服务器之间的所有通信通过客户端侧的代理和服务器侧的桩进行。代理和桩负责编码和解码数据和通过 Binder 驱动程序发送的命令。为了使用代理和桩,开发人员只需定义一个 AIDL 接口,在编译应用程序期间将其转换为代理和桩。在服务端,调用单独的 Binder 线程来处理客户端请求。

    从技术上讲,使用Binder机制的每个公开服务(有时称为 Binder 服务)都分配有标识。内核驱动程序确保此 32 位值在系统中的所有进程中是唯一的。因此,此标识用作 Binder 服务的句柄。拥有此句柄可以与服务交互。然而,为了开始使用服务,客户端首先必须找到这个值。服务句柄的发现通过 Binder 的上下文管理器(servicemanager是 Android Binder 的上下文管理器的实现,在这里我们互换使用这些概念)来完成。上下文管理器是一个特殊的 Binder 服务,其预定义的句柄值等于 0(指代清单 4.1 的第 8 行中获得的东西)。因为它有一个固定的句柄值,任何一方都可以找到它并调用其方法。基本上,上下文管理器充当名称服务,通过服务的名称提供服务句柄。为了实现这个目的,每个服务必须注册上下文管理器(例如,使用第 26 行中的ServiceManager类的addService方法)。因此,客户端可以仅知道与其通信的服务名称。使用上下文管理器来解析此名称(请参阅getService第 12 行),客户端将收到稍后用于与服务交互的标识。 Binder 驱动程序只允许注册单个上下文管理器。因此,servicemanager是由 Android 启动的第一个服务之一(见第 3.1 节)。servicemanager组件确保了只允许特权系统标识注册服务。

    Binder 框架本身不实施任何安全性。 同时,它提供了在 Android 中实施安全性的设施。 Binder 驱动程序将发送者进程的 UID 和 PID 添加到每个事务。 因此,由于系统中的每个应用具有其自己的 UID,所以该值可以用于识别调用方。 调用的接收者可以检查所获得的值并且决定是否应该完成事务。 接收者可以调用android.os.Binder.getCallingUid()android.os.Binder.getCallingPid()[12]来获得发送者的 UID 和 PID。 另外,由于 Binder 句柄在所有进程中的唯一性和其值的模糊性[14],它也可以用作安全标识。

     1 public final class ServiceManager { 
     2   ... 
     3   private static IServiceManager getIServiceManager() { 
     4     if ( sServiceManager != null ) { 
     5       return sServiceManager ; 
     6     } 
     7     // Find the service manager 
     8     sServiceManager = ServiceManagerNative.asInterface( BinderInternal.getContextObject() ); 
     9     return sServiceManager ; 
    10   } 
    11 
    12   public static IBinder getService ( String name) { 
    13     try { 
    14       IBinder service = sCache . get (name) ; 
    15       if ( service != null ) { 
    16         return service ; 
    17       } else { 
    18         return getIServiceManager().getService(name); 
    19       } 
    20     } catch (RemoteException e) { 
    21       Log.e(TAG, "error in getService", e); 
    22     } 
    23     return null; 
    24   } 
    25 
    26   public static void addService( String name, IBinder service, boolean allowIsolated ) { 
    27     try { 
    28       getIServiceManager().addService(name, service, allowIsolated ); 
    29     } catch (RemoteException e) { 
    30       Log.e(TAG, "error in addService" , e); 
    31     } 
    32   } 
    33   ... 
    34 }

    代码 4.1:ServiceManager的源码

    4.2 Android 权限

    如我们在 2.1 节中所设计的那样,在 Android 中,每个应用程序默认获得其自己的 UID 和 GID 系统标识。 此外,在操作系统中还有一些硬编码的标识(参见清单 3.5)。 这些身份用于使用在 Linux 内核级别上实施的 DAC,分离 Android 操作系统的组件,从而提高操作系统的整体安全性。 在这些身份中,AID SYSTEM最为显著。 此 UID 用于运行系统服务器(system server),这个组件统一了由 Android 操作系统提供的服务。 系统服务器具有访问操作系统资源,以及在系统服务器内运行的每个服务的特权,这些服务提供对其他 OS 组件和应用的特定功能的受控访问。 此受控访问基于权限系统。

    正如我们在 4.1 节中所提及的,Binder 框架向接收方提供了获得发送方 UID 和 PID 的能力。在一般情况下,该功能可以由服务利用来限制想要连接到服务的消费者。这可以通过将消费者的 UID 和 PID 与服务所允许的 UID 列表进行比较来实现。然而,在 Android 中,这种功能以略微不同的方式来实现。服务的每个关键功能(或简单来说是服务的方法)被称为权限的特殊标签保护。粗略地说,在执行这样的方法之前,会检查调用进程是否被分配了权限。如果调用进程具有所需权限,则允许调用服务。否则,将抛出安全检查异常(通常,SecurityException)。例如,如果开发者想要向其应用程序提供发送短信的功能,则必须将以下行添加到应用程序的AndroidManifest.xml文件中:<uses-permission android:name ="android.permission.SEND_SMS"/> 。Android 还提供了一组特殊调用,允许在运行时检查服务使用者是否已分配权限。

    到目前为止所描述的权限模型提供了一种强化安全性的有效方法。 同时,这个模型是无效的,因为它认为所有的权限是相等的。 在移动操作系统的情况下,所提供的功能在安全意义上并不总是相等。 例如,安装应用程序的功能比发送 SMS 的功能更重要,相反,发送 SMS 的功能比设置警告或振动更危险。

    这个问题在 Android 中通过引入权限的安全级别来解决。有四个可能的权限级别:normaldangeroussignaturesignatureOrSystem。权限级别要么硬编码到 Android 操作系统(对于系统权限),要么由自定义权限声明中的第三方应用程序的开发者分配。此级别影响是否决定向请求的应用程序授予权限。为了被授予权限,正常的权限可以只在应用程序的AndroidManifest.xml文件中请求。危险权限除了在清单文件中请求之外,还必须由用户批准。在这种情况下,安装应用程序期间,安装包所请求的权限集会显示给用户。如果用户批准它们,则安装应用程序。否则,安装将被取消。如果请求权限的应用与声明它的应用拥有相同签名,(6.1 中提到了 Android 中的应用程序签名的用法),系统将授予signature权限。如果请求的权限应用和声明权限的使用相同证书签名,或请求应用位于系统映像上,则授予signatureOrSystem权限。因此,对于我们的示例,振动功能被正常级别的权限保护,发送 SMS 的功能被危险级别的权限保护,以及软件包安装功能被signatureOrSystem权限级别保护。

    4.2.1 系统权限定义

    用于保护 Android 操作系统功能的系统权限在框架的AndroidManifest.xml文件中定义,位于 Android 源的frameworks/base/core/res文件夹中。 这个文件的一个摘录包含一些权限定义的例子,如代码清单 4.2 所示。 在这些示例中,展示了用于保护发送 SMS,振动器和包安装功能的权限声明。

     1 <manifest xmlns:android=" http://schemas.android.com/apk/res/android" 
     2   package="android" coreApp="true" android:sharedUserId="android.uid.system" 
     3   android:sharedUserLabel="@string/android_system_label "> 
     4   ... 
     5   <!−− Allows an application to send SMS messages. −−> 
     6   <permission android:name="android.permission.SEND_SMS" 
     7     android:permissionGroup="android.permission−group.MESSAGES" 
     8     android:protectionLevel="dangerous"
     9     android:permissionFlags="costsMoney" 
    10     android:label="@string/permlab_sendSms" 
    11     android:description="@string/permdesc _sendSms" /> 
    12   ... 
    13   <!−− Allows access to the vibrator −−> 
    14   <permission android:name="android.permission.VIBRATE" 
    15     android:permissionGroup="android.permission−group.AFFECTS_BATTERY" 
    16     android:protectionLevel="normal" 
    17     android:label="@string/permlab_vibrate" 
    18     android:description="@string/permdesc_vibrate" /> 
    19   ... 
    20   <!−− Allows an application to install packages. −−> 
    21   <permission android:name="android.permission.INSTALL_PACKAGES" 
    22     android:label="@string/permlab_installPackages" 
    23     android:description="@string/permdesc_installPackages" 
    24     android:protectionLevel="signature|system" /> 
    25   ... 
    26 </manifest>

    代码 4.2:系统权限的定义

    默认情况下,第三方应用程序的开发人员无法访问受signaturesignatureOrSystem级别的系统权限保护的功能。 这种行为以以下方式来保证:应用程序框架包使用平台证书签名。 因此,需要使用这些级别的权限保护的功能的应用程序必须使用相同的平台证书进行签名。 然而,仅有操作系统的构建者才可以访问该证书的私钥,通常是硬件生产者(他们自己定制 Android)或电信运营商(使用其修改的操作系统映像来分发设备)。

    4.2.2 权限管理

    系统服务PackageManagerService负责 Android 中的应用程序管理。 此服务有助于在操作系统中安装,卸载和更新应用程序。 此服务的另一个重要作用是权限管理。 基本上,它可以被认为是一个策略管理的要素。 它存储了用于检查 Android 包是否分配了特定权限的信息。 此外,在应用程序安装和升级期间,它执行一堆检查,来确保在这些过程中不违反权限模型的完整性。 此外,它还作为一个策略判定的要素。 此服务的方法(我们将在后面展示)是权限检查链中的最后一个元素。 我们不会在这里考虑PackageManagerService的操作。 然而,感兴趣的读者可以参考[15,19]来获得如何执行应用安装的更多细节。

    PackageManagerService将所有第三方应用程序的权限的相关信息存储在/data/system/packages.xml[7]中。 该文件用作系统重新启动之间的永久存储器。 但是,在运行时,所有有关权限的信息都保存在 RAM 中,从而提高系统的响应速度。 在启动期间,此信息使用存储在用于第三方应用程序的packages.xml文件中的数据,以及通过解析系统应用程序来收集。

    4.2.3 Android 框架层的权限实施

    为了了解 Android 如何在应用程序框架层强制实施权限,我们考虑 Vibrator 服务用法。 在清单 4.3 的第 6 行中,展示了振动器服务如何保护其方法vibrate的示例。 这一行检查了调用组件是否分配有由常量android.Manifest.permission.VIBRATE定义的标签android.permission.VIBRATE。 Android 提供了几种方法来检查发送者(或服务使用者)是否已被分配了权限。 在我们这个库,这些设施由方法checkCallingOrSelfPermission表示。 除了这种方法,还有许多其他方法可以用于检查服务调用者的权限。

     1 public class VibratorService extends IVibratorService.Stub 
     2   implements InputManager.InputDeviceListener { 
     3   ... 
     4   public void vibrate ( long milliseconds, IBinder token ) { 
     5     if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 
     6             != PackageManager.PERMISSION_GRANTED) { 
     7       throw new SecurityException("Requires VIBRATE permission"); 
     8     } 
     9     ... 
    10   } 
    11   ... 
    12 }

    代码 4.3:权限的检查

    方法checkCallingOrSelfPermission的实现如清单 4.4 所示。 在第 24 行中,方法checkPermission被调用。 它接收uidpid作为 Binder 框架提供的参数。

     1 class ContextImpl extends Context { 
     2   ... 
     3   @Override 
     4   public int checkPermission ( String permission, int pid, int uid ) { 
     5     if ( permission == null ) { 
     6       throw new IllegalArgumentException ("permission is null ") ; 
     7     } 
     8 
     9     try { 
    10       return ActivityManagerNative.getDefault().checkPermission( 
    11         permission, pid, uid ); 
    12       } catch (RemoteException e) { 
    13       return PackageManager.PERMISSION_DENIED; 
    14     } 
    15   } 
    16 
    17   @Override 
    18   public int checkCallingOrSelfPermission ( String permission ) { 
    19     if ( permission == null ) { 
    20       throw new IllegalArgumentException("permission is null"); 
    21     } 
    22 
    23     return checkPermission( permission, Binder. getCallingPid(), 
    24       Binder.getCallingUid() ); 
    25   } 
    26   ... 
    27 }

    代码 4.4:ContextImpl类的摘录

    在第 11 行中,检查被重定向到ActivityManagerService类,继而在ActivityManager组件的方法checkComponentPermission中执行实际检查。 此方法的代码如清单 4.5 所示。 在第 4 行中它检查调用者 UID 是否拥有特权。 具有 root 和系统 UID 的组件由具有所有权限的系统授予。

     1 public static int checkComponentPermission ( String permission, int uid, 
     2   int owningUid, boolean exported ) { 
     3   // Root , system server get to do everything . 
     4   if ( uid == 0 || uid == Process.SYSTEM_UID) { 
     5     return PackageManager.PERMISSION_GRANTED; 
     6   } 
     7   // Isolated processes don ’ t get any permissions . 
     8   if ( UserId.isIsolated ( uid ) ) { 
     9     return PackageManager.PERMISSION_DENIED; 
    10   } 
    11   // If there is a uid that owns whatever is being accessed , it has 
    12   // blanket access to it regardless of the permissions it requires . 
    13   if (owningUid >= 0 && UserId.isSameApp(uid, owningUid) ) { 
    14     return PackageManager.PERMISSION_GRANTED; 
    15   } 
    16   // If the target is not exported , then nobody else can get to it . 
    17   if (!exported) { 
    18     Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid) ; 
    19     return PackageManager.PERMISSION_DENIED; 
    20   } 
    21   if ( permission == null ) { 
    22     return PackageManager.PERMISSION_GRANTED; 
    23   } 
    24   try { 
    25     return AppGlobals.getPackageManager() 
    26       .checkUidPermission ( permission , uid ) ; 
    27   } catch (RemoteException e) { 
    28     // Should never happen , but if it does . . . deny !
    29     Slog.e(TAG, "PackageManager is dead ?!?" , e) ; 
    30   } 
    31   return PackageManager.PERMISSION_DENIED;
    32 }

    代码 4.5:ActivityManagercheckComponentPermission方法。

    在清单 4.5 的第 26 行中,权限检查被重定向到包管理器,将其转发到PackageManagerService。 正如我们前面解释的,这个服务知道分配给 Android 包的权限。 执行权限检查的PackageManagerService方法如清单 4.6 所示。 在第 7 行中,如果将权限授予由其 UID 定义的 Android 应用程序,则会执行精确检查。

     1 public int checkUidPermission ( String permName, int uid ) { 
     2  final boolean enforcedDefault = isPermissionEnforcedDefault(permName); 
     3  synchronized (mPackages) { 
     4    Object obj = mSettings.getUserIdLPr( UserHandle.getAppId( uid ) ); 
     5    if ( obj != null ) { 
     6      GrantedPermissions gp = ( GrantedPermissions ) obj ; 
     7      if (gp.grantedPermissions.contains (permName) ) { 
     8        return PackageManager.PERMISSION_GRANTED; 
     9      } 
    10    } else { 
    11      HashSet<String> perms = mSystemPermissions.get ( uid ) ; 
    12      if (perms != null && perms.contains (permName) ) { 
    13        return PackageManager.PERMISSION_GRANTED; 
    14      } 
    15    } 
    16    if (!isPermissionEnforcedLocked (permName, enforcedDefault ) ) { 
    17      return PackageManager.PERMISSION_GRANTED; 
    18    } 
    19  } 
    20  return PackageManager .PERMISSION DENIED; 
    21 }

    代码 4.6:PackageManagerServicecheckUidPermission方法

    展开全文
  • QMUI_Android框架使用教程

    千次阅读 2018-02-28 15:04:58
    QMUI_Android框架 github地址:点击打开链接功能特性全局 UI 配置只需要修改一份配置表就可以调整 App 的全局样式,包括组件颜色、导航栏、对话框、列表等。一处修改,全局生效。丰富的 UI 控件提供丰富常用的 UI ...
  • Android框架之路——Studio如何导入Github开源项目 软件框架搭建; 一、UI ToolBar的使用; Android框架之路——ToolBar的使用 NavigationView侧边栏的使用; Android框架之路——NavigationView的使用(结合...
  • 图解Google官方示例的各种android框架

    千次阅读 2017-04-05 18:04:26
    Goolge官方的Android框架源码见:GitHub工程; 毋庸置疑,官方给出的框架示例应该是最标准也最具有普适性的。本文根据工程中的示例,画出了各个框架的架构图,以方便快速学习和了解。 1。常见的MVC框架如下图所示...
  • 最新Android框架排行榜,上百项资源汇总不容错过

    千次阅读 多人点赞 2019-05-21 17:30:36
    Android框架排行榜1.Retrofit 一句话介绍:Retrofit是一款类型安全的网络框架,基于HTTP协议,服务于Android和java语言上榜理由:Retrofit以21.8k的stars量雄踞github中android子标题榜首,第一当之无愧。...
  • Android 框架练成 教你打造高效的图片加载框架

    万次阅读 多人点赞 2014-12-12 09:29:07
    转载请标明出处:...但是作为一名合格的程序猿,必须懂其中的实现原理,于是乎,今天我就带大家一起来设计一个加载网络、本地的图片框架。有人可能会说,自己
  • Android框架之MVC模式(以登录为例)

    千次阅读 2018-07-15 19:30:12
    Android框架现在常见的有MVC模式、MVP模式、MVVM模式。我们首先先明确一个概念:模式是指组织代码的结构方式,模式并不能提高代码的执行效率。模式是为了后续功能的扩展方便和代码的结构清晰而使用的。 刚开始做...
  • 开始使用QMUI Android框架,找找使用教程,网上一大堆的把官网的三段话复制一遍。实际上要到真正的运行起来,远远还不是这么简单,官网的教程适合有一定编程基础的人员,想我这样刚刚接触Android开发的,摸索了好久...
  • Android 框架类图

    千次阅读 2015-04-15 17:28:59
    理了一下Android: Context、 Activity、 View、 ViewRootImpl、 WindowManager、Window、WindowManagerGlobal之间的类关系如下图:比较大,可能需要加载一会。。。
  • (一).前言:    前面我们已经对于AndroidAnnotations使用Adapters和lists做了讲解,今天我们开始具体学习一下使用DI框架SharedPreferencesHelpers的使用,SharedPreferencesHelpers... FastDev4Android框架项目地址
  • 上一篇文章中,已经正常的将QMUI框架引入到项目中了,并且实现了...上一篇链接:QMUI Android框架初步使用1-环境配置到正常现实对话框这次继续在上一篇的基础上,将状态栏改为沉浸式,即修改为跟官方demo效果一样。...
  • android框架结构

    万次阅读 2011-02-24 15:32:00
    直接上图由上图,我们可以看出Android系统架构由5部分组成,分别是:Linux Kernel(linux内核)、Android Runtime(运行时环境)、Libraries(类库)、Application Framework(应用框架)、Applications(应用)。...
  • 本项目是Android快速开发框架,采用AndroidStudio进行开发。 随着公司项目的不断深入,也相信每个公司都有自己的项目开发框架,同时也在不断的完善,本人在工作中也在不断总结,喜欢技术,热爱开源,也乐于和各种技术...
  • (一).前言:    前面我们已经对于AndroidAnnotations框架集成Otto事件总线做了讲解,今天我们开始具体学习一下第三方框架集成Ormlite... FastDev4Android框架项目地址:https://github.com/jiangqqlmj/FastDev4Android
  • Android框架之路——EventBus的使用

    万次阅读 多人点赞 2017-05-09 16:52:54
    EventBus是由greenrobot 组织贡献的一个Android事件发布/订阅轻量级框架。EventBus是一个Android端优化的publish/subscribe消息总线,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回...
  • Android框架之路——OkGo的使用

    万次阅读 多人点赞 2017-05-10 22:26:59
    该库是封装了okhttp的标准RESTful风格的网络框架,可以与RxJava完美结合,比Retrofit更简单易用。支持大文件上传下载,上传进度回调,下载进度回调,表单上传(多文件和多参数一起上传),链式调用,可以自定义返回...
  • QMUI Android框架的官方说,QMUIGroupListView一般用于设置页面,如下图所示是官方说的。但是官方给出的样例demo仅仅也就展示了4个样例,显示文本、箭头、开关和加载效果。一个设置中心要放置的表单元素种类太多了,...
  • ANDROID框架结构和介绍

    千次阅读 2014-07-07 17:02:58
    下图是ANDROID4.4 版本包含的所有系统服务和本地服务和应用的框架图,baoh
  • android 框架

    千次阅读 2011-08-26 14:18:18
     What makes an Android phone an Android phone rather than a mobile Linux implementation is the Android run time. Including the core libraries and the Dalvik virtual machine, the Android run time ...
  • android 框架试用--spring for android

    万次阅读 2013-06-19 20:20:25
    参考资料: http://www.chenwg.com/android/spring-android%E7%9A%84%E4%BD%BF%E7%94%A8.html ... spring-android主要提供了
  • 2018年60个实用Android框架排行榜

    万次阅读 多人点赞 2018-04-16 00:33:40
    qq交流群:6685241181.Retrofit一句话介绍:Retrofit是一款类型安全的网络框架,基于HTTP协议,服务于Android和java语言上榜理由:Retrofit以21.8k的stars量雄踞github中android子标题榜首,第一当之无愧。...
  • (一).前言:    今天我们的项目继续更新,今天主要要加入一个非常漂亮的进度指示器AVLoadingIndicatorView(开源地址)... FastDev4Android框架项目地址:https://github.com/jiangqqlmj/FastDev4Android  (二).简要介
  • AndroidAnnotations是一个能够让你快速进行Android开发的开源框架,它可以让我更加专注于业务功能开发。并且使代码更加精简,使项目更加容易维护,它的目标就是“Fast Android Development.Easymaintainance”。...
  • buildscript { dependencies { // 顺便也配置了支持lambda表达式 classpath 'me.tatarka:gradle-retrolambda:3.2.4' // classpath 'com.android.tools.build:gradle:3.0.1' 正常gradle插件配置 } }

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 86,607
精华内容 34,642
关键字:

android框架