Android开发基础(一)
本篇主要是从Android系统架构理解Android开发。
Android系统的架构采用了分层的架构,共分为五层,从高到低分别是Android应用层(System Apps)、Android应用框架层(Java API Framework)、Android系统运行库层(Native)、硬件抽象层(HAL)和Linux内核层(Linux Kernel);
这种分层架构使得Android系统更加模块化,易于维护和扩展。
Android应用层是Android系统架构中的最高层,它直接与用户交互,提供丰富的应用程序供用户使用;
这一层主要包括各种应用程序,如邮件客户端、SMS短消息程序、日历、地图、浏览器、联系人管理程序等,所有这些应用程序都是使用Java语言编写的;
它们通过Android提供的应用程序框架来访问系统服务和资源,实现各种功能;
此外,Android应用层还提供了一些核心应用程序,如主屏幕(HOME)、联系人(Contacts)、电话(Phone)和浏览器(Browser)等;
这些应用程序是Android系统的基本组成部分,用于实现基本的手机功能;
开发人员可以根据需要替换或开发新的应用程序,以扩展Android系统的功能;
在应用框架层,开发人员可以完全访问核心应用程序所使用的API框架。
// 导入所需的API框架
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MyActivity extends Activity {
// 定义一个TextView对象,用于显示文本
private TextView textView;
// 在onCreate()方法中初始化TextView对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
setContentView(textView);
}
// 在onResume()方法中更新TextView对象的文本内容
@Override
protected void onResume() {
super.onResume();
textView.setText("Hello, World!");
}
}
Android应用框架层是Android系统中的一层,位于应用层之下,系统运行库层和Linux内核层之上;
这一层是Android应用开发的核心,为开发者在开发应用时提供基础的API框架。这一层集中体现了Android系统的组件设计思想,并且由多个系统服务组成;
Android应用框架层支持包括Activity Manager(活动管理器)、Window Manager(窗口管理器)、Content Providers(内容提供者)、View System(视图系统)、Notification Manager(通知管理器)、Package Manager(包管理器)、Telephony Manager(电话管理器)、Resource Manager(资源管理器)、Location Manager(位置管理器)和XMPPServices(XMPP服务)等在内的多个部分;
其中,Android活动管理器(Activity Manager)用于管理应用程序的生命周期,并提供常用的导航回退功能;
而View System主要用于UI设计,包括List、Grid、Text、Button、Webview等;
此外,Android应用框架层还提供了各种API供开发者使用,例如android.content用于访问和发布各种设备上的数据,android.database则通过内容提供者浏览和操作数据库。
// 获取设备信息
String model = Build.MODEL;
String manufacturer = Build.MANUFACTURER;
// 访问网络
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
// 访问数据库
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM table_name", null);
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
// Do something with the data...
}
cursor.close();
db.close();
// 启动活动(Activity)
Intent intent = new Intent(this, AnotherActivity.class);
startActivity(intent);
// 发送通知
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channel_id")
.setContentTitle("Content Title")
.setContentText("Content Text")
.setSmallIcon(R.drawable.notification_icon);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, builder.build());
Android系统的运行库层主要分为两部分:C/C++程序库和Android运行时库;
C/C++程序库能够被Android系统中的不同组件使用,并通过应用程序框架为开发者提供服务;
主要的C/C++程序库包括OpenGL ES(3D绘图函数库)、Libc(从BSD继承来的标准C系统函数库,专门为基于嵌入式Linux的设备定制)、Media Framework(多媒体库,支持多种常用的音频、视频格式录制和回放)、SQLite(轻型的关系型数据库引擎)、SGL(底层的2D图形渲染引擎)、SSL(安全套接层,一种为网络通信提供安全及数据完整性的安全协议)以及FreeType(可移植的字体引擎,提供统一的接口来访问多种字体格式文件);
Android运行时库分为核心库和ART(Android 5.0之前为Dalvik虚拟机,在5.0之后被ART取代);
运行时库提供了核心库和Java语言核心库的大多数功能,开发者可使用Java语言来编写Android应用;
此外,还包含了虚拟机Dalvik(但之后改为了ART运行环境),使每一个Android应用都有自己的进程,并且都有一个自己的Dalvik虚拟机实例;
相较于JAVA的虚拟机,Dalvik是专门为移动设备定制的,针对内存和CPU性能都有了优化。
// 使用数据库
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "mydatabase.db";
private static final int DATABASE_VERSION = 1;
public MyDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE = "CREATE TABLE mytable (id INTEGER PRIMARY KEY, name TEXT)";
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS mytable");
onCreate(db);
}
public void addData(String name) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name", name);
db.insert("mytable", null, values);
db.close();
}
public Cursor getData() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM mytable", null);
return cursor;
}
}
// 画个圆
@Override
public void onDrawFrame(GL10 gl) {
// 清除颜色和深度缓冲
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 设置为不进行背面剪裁
gl.glDisable(GL10.GL_CULL_FACE);
// 设置为使用RGBA颜色模式
gl.glColor4f(1, 1, 1, 1); // 设置颜色为白色
gl.glShadeModel(GL10.GL_FLAT); // 设置着色模型为平面着色
// 绘制一个填充的圆形,使用正弦和余弦函数来创建圆形路径
gl.glBegin(GL10.GL_TRIANGLE_FAN); // 开始绘制一个由三角形的扇形组成的圆
for (int i = 0; i <= 90; i++) { // 绘制90个点,形成一个完整的圆
float a = i * (2*Math.PI/90); // 角度转弧度
float x = 50 * (float)Math.cos(a); // x坐标计算
float y = 50 * (float)Math.sin(a); // y坐标计算
gl.glVertex2f(x, y); // 添加顶点到路径
}
gl.glEnd(); // 结束绘制路径
}
Android的硬件抽象层(HAL)是一个接口层,它允许应用程序与特定硬件设备进行交互,而无需了解底层硬件的细节;
HAL提供了一种标准化的方式来访问硬件组件,使得应用程序可以在不同的设备和Android版本上保持一致的行为;
HAL的主要目的是将硬件驱动程序与Android系统软件分离,使得硬件厂商可以提供符合标准接口的驱动程序,而无需修改Android系统软件;
这有助于降低硬件和软件之间的耦合度,提高系统的可移植性和可维护性。
在Android中,HAL采用C/C++编写,因为这些语言可以更直接地与硬件交互;
HAL定义了一组标准化的接口,这些接口描述了应用程序可以执行的操作以及它们需要的参数;
硬件厂商需要提供实现这些接口的代码,以便应用程序可以通过HAL与硬件进行通信;
通过HAL,应用程序可以使用标准的API来访问硬件组件,例如相机、传感器、音频编解码器等;
这样,应用程序可以在不同的设备和Android版本上保持一致的行为,而无需针对不同的硬件平台进行定制开发。
// 音频解码
public interface AudioDecoderHal {
void open();
void setDecodingParams(int sampleRate, int channelConfig, int audioFormat);
void startDecoding();
void stopDecoding();
// 其他相关操作...
}
// 假设你已经获取到了AudioDecoderHal实例
AudioDecoderHal decoderHal = ...; // 从适当的地方获取实例
// 打开音频流
decoderHal.open();
// 设置解码参数
decoderHal.setDecodingParams(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
// 开始解码
decoderHal.startDecoding();
// ... 在此处处理解码后的数据 ...
// 停止解码
decoderHal.stopDecoding();
Android系统的Linux内核层是Android核心系统的基础,它为Android设备的各种硬件提供底层的驱动,如显示驱动、音频驱动、键盘驱动、电源驱动等;
该层还负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能;
Android选择采用Linux内核的原因与Linux的特性有关,包括强大的内存管理和进程管理、基于权限的安全模式、支持共享库、经过认证的驱动模式等;
同时,Linux本身就是开源项目,这也符合Android开源的特性;
内存管理主要包括物理内存和虚拟内存管理;
在物理内存管理方面,Android主要使用了Low Memory Killer机制,该机制会根据进程的优先级和空闲内存量来决定杀死哪些进程,从而回收内存;
虚拟内存管理方面,Linux内核提供了虚拟内存机制,使得应用程序看到的内存是连续的,而实际的物理内存可能是分散的;
Android在此基础上进行了定制和优化,例如通过Dalvik虚拟机和ART运行环境来管理应用程序的内存分配和回收;
此外,Android系统还引入了多种优化技术来提高内存管理的效率和性能,例如使用内存压缩技术、智能回收技术等;
这些技术有助于减少应用程序的内存占用和提高系统的整体性能。
Android的引用计数是一种内存管理技术,用于跟踪和管理对象的生命周期;
通过引用计数,系统可以确定何时释放不再使用的对象,以释放内存;
在Android中,每个对象都有一个与之关联的引用计数器;
当一个对象被创建时,引用计数器初始化为1;
当一个引用指向该对象时,计数器增加1;
当引用被删除或失效时,计数器减少1;
当引用计数器减少到0时,这意味着没有任何引用指向该对象,因此系统可以安全地释放该对象所占用的内存;
Android的引用计数机制有助于防止内存泄漏和确保及时释放不再使用的对象;
public class LeakyActivity extends AppCompatActivity {
private static final String TAG = "LeakyActivity";
private static final int MAX_POOL_SIZE = 10;
private static final Object sPoolMutex = new Object();
private static LinkedBlockingQueue<Bitmap> sBitmapPool = new LinkedBlockingQueue<>(MAX_POOL_SIZE);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaky);
Button button = findViewById(R.id.leak_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bitmap bitmap = createBitmap();
if (bitmap != null) {
if (sBitmapPool.size() < MAX_POOL_SIZE) {
sBitmapPool.add(bitmap);
} else {
Log.w(TAG, "Bitmap pool is full, not adding more bitmaps.");
}
} else {
Log.e(TAG, "Failed to create bitmap.");
}
}
});
}
private Bitmap createBitmap() {
// 创建Bitmap的代码...
return bitmap;
}
}
以上是一个Android内存泄漏代码示例,由于 sBitmapPool 是静态的,它会在整个应用程序的生命周期内存在,即使 LeakyActivity 已经不再使用;
这意味着即使 LeakyActivity 已经被销毁,但由于池仍然存在并持有对 Bitmap 对象的引用,这些对象将无法被垃圾回收器回收,从而导致内存泄漏;
下面介绍一个循环引用导致内存泄漏的示例。
public class MyActivity extends AppCompatActivity {
private MyCustomView customView;
private View.OnTouchListener listener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
customView.onTouchEvent(event);
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
customView = findViewById(R.id.custom_view);
customView.setOnTouchListener(listener);
}
}
public class MyCustomView extends View {
private MyActivity activityRef;
// ...其他成员变量和方法...
public void attachActivity(MyActivity activity) {
this.activityRef = activity;
// ...执行其他操作...
}
}