10.27学习

apk结构

META-INF目录:存放签名,用来保证apk包的完整性和系统安全

assets目录:用于存放需要打包到APK中的静态文件。res目录下的文件会在.R文件中生成对应的资源ID,assets不会自动生成对应的ID,访问的时候需要AssetManager类。

lib目录:这里存放应用程序依赖的native库文件,一般是用C/C++编写,这里的lib库可能包含4中不同类型,根据CPU型号的不同,大体可以分为ARM架构,ARM-V7a架构,MIPS架构和X86架构。

res目录:存放资源文件,存在这个文件夹下的所有文件都会映射到Android工程的.R文件中,生成对应的ID,访问的时候直接使用资源ID即R.id.filename,res文件夹下可以包含多个文件夹。

AndroidMainfes.xml:是Android应用程序的配置文件,开发Android应用程序的时候,一般都把代码中的每一个Activity,Service,Provider和Receiver在AndroidManifest.xml中注册,只有这样系统才能启动对应的组件,另外这个文件还包含一些权限声明以及使用的SDK版本信息等等。程序打包时,会把AndroidManifest.xml进行简单的编译,便于Android系统识别,编译之后的格式是AXML格式。

classes.dex :.class文件:Java文件编译生成的的字节码都保存在其中,一个类生成一个class文件

​ .dex文件:先生成class文件,Android应用在打包时通过AndroidSDK中dx工具将java字节码转换成Dalvik字节码,dx工具可以对多个class文件进行合并,重组,优化。

resources.arsc:用来记录资源文件和资源id之间的映射关系,用来根据资源id寻找资源。Android的开发是分模块的,res目录专门用来存放资源文件,当在代码中需要调用资源文件时,只需要调用findviewbyId()就可以得到资源文件,每当在res文件夹下放一个文件,aapt就会自动生成对应的ID保存在.R文件,我们调用这个ID就可以,但是只有这个ID还不够,.R文件只是保证编译程序不报错,实际上在程序运行时,系统要根据ID去寻找对应的资源路径,而resources.arsc文件就是用来记录这些ID和资源文件位置对应关系的文件。

—>resouces.arsc映射逻辑https://juejin.im/post/6844903911602683918

索引是指在R.java文件中生的资源ID:

1
2
3
4
5
public final class R{
public static final class drawable {
public static final int icon=0x7f020000;
}
}

格式为:0xPPTTEEEE。

esouces.arsc文件结构分为几大类:

  • RES_TABLE_TYPE(描述的是整个resources.arsc的属性)

  • RES_STRING_POOL_TYPE(字符串资源池,主要存储字符串,注意这里的字符串资源池不包括资源类型和资源名)

  • RES_TABLE_PACKAGE_TYPE(是一个包的概念,主要记录资源类型偏移和包名偏移,索引串0xPPTTEEEE中的PP的值一般为7f)

  • RES_TABLE_TYPE_SPEC_TYPE(代表资源类型,Android中资源有attr,drawable,layout等,每一个类型都有这样的一个结构,所以在块中有多个,每个资源类型结构后面会跟着包名的数组,如drawable类型有多个尺寸的,所以有多少种尺寸后面就会跟着多少个RES_TABLE_TYPE_TYPE块,索引串0xPPTTEEEE中的TT的值

  • RES_TABLE_TYPE_TYPE (每一个RES_TABLE_TYPE_TYPE里面包含一个ResTable_entry的数组,每一个资源的具体内容;注意上图中有一个ResTable_entry的偏移数组,这个数组就是0xPPTTEEEE中的EEEE;资源分bag和非bag类型,bag类型是值是确定的,非bag类型的值是有多个的)

Android四大组件

一.Activity

Activity

1.1生命周期

生命周期

1.2Activity的创建流程

  1. 自定义Activity类名,继承Activity类或者它的子类
  2. 重写onCreate()方法,在该方法中调用setContentView()设置要显示的视图
  3. 再AndroidManifest.xml对Activity进行配置
  4. 启动Activity
  5. 关闭activity

1.3activity数据状态保存onSaveInstanceState

一个参数:

1
2
3
4
5
@override
public void onCreate (Bundle savedInstantanceState){
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
}

一般情况下,只有一个参数,页面数据短暂保存,返回或暂时离开或者横竖屏切换时调用onSaveInstanceState(Bundle outState),再返回调用onRestoreInstanceState(Bundle saveInstanceState)

两个参数

1
2
3
4
@override
public void onCreate (Bundle saveInstanceState,PersistableBundle persistentState){
super.onCreate(saveInstanceState,persistentState);
}

PersistableBundle参数来自配置文件中我们设置的Activity设置的一个属性:

1
android:persistableMode=“persistAcrossReboots(重启设备,会持久化页面的数据或者状态)|persistRootOnly|persistNever"

这样Activity拥有了持久化的能力,系统关机后重启的数据恢复能力。

ContentProvider

一个应用的数据允许被另一个应用读取操作,可以通过ContentProvider类来实现,同时注册一个uri,使用ContentProvide根据uri就可以操作app中的数据

利用contentprovider读取短信联系人

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.example.sms;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

private ListView listView;
private ContentResolver cr;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getMsgs();
}

private void getMsgs() {
Uri uri = Uri.parse("content://sms/");
ContentResolver resolver = getContentResolver();
//获取的是哪些列的信息
Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null);
while(cursor.moveToNext())
{
String address = cursor.getString(0);
String date = cursor.getString(1);
String type = cursor.getString(2);
String body = cursor.getString(3);
System.out.println("地址:" + address);
System.out.println("时间:" + date);
System.out.println("类型:" + type);
System.out.println("内容:" + body);
System.out.println("======================");
}
cursor.close();
}
}

AndroidMainfest.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sms">
<uses-permission android:name="android.permission.READ_SMS"/>
//获取权限
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Sms">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

问题:运行时,发现不能获取权限。