周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周天 |
---|---|---|---|---|---|---|
Linux内核层
系统运行库层
这一层主要包括一些C/C++库为Android系统提供功能上的支持。
同时还包括Android运行时所必需的核心库,允许开发人员使用Java语言来编写Android应用程序。
Dalvik虚拟机,每个Android程序运行时会启动一个新的Dalvik虚拟机,保证各进程的独立性。与在PC端运行的Java虚拟机不同,Dalvik虚拟机是针对移动设备定制的,并进行了相应的优化。(Android5.0系统后改为ART运行环境)
应用框架层
应用层
build:包含一些在编译时自动生成的文件,无需过多关心。
libs:项目中使用到的第三方Jar包存放在此目录下,会被自动添加到构建路径里。
androidTest:编写测试用例用的。
java:存放所有Java代码的地方。
res:存放项目中使用到的所有资源文件。包含以下子目录:
AndroidManifest.xml:整个Android项目的配置文件,程序中定义的组件都需要在这个文件中注册,同时可以给程序添加权限声明(非常重要,之后逆向的学习也会用到)。
build.gradle:APP模块的gradle构建脚本。
proguard-rules.pro:用于指定项目代码的混淆规则,之后学习Android应用保护手段的时候也会用到。
Android中的日志工具类是Log(Android.util.Log),提供以下五种方法打印日志:
在Hello World项目中加入如下代码试用:
Log.d("MainActivity","onCreate execute");
两种方式如下:
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState)
}
需要在AndroidManifest.XML文件中进行注册。(AS中,创建一个新活动后会默认自动帮你注册好)
<activity android:name=".活动名"></activity/>
程序运行时首先运行的活动。需要在
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
是Android程序中各组件之间进行交互的重要方式,还可以在不同组件中传递数据,一般用于启动活动,启动服务以及发送广播等场景。分为显式Intent和隐式Intent。
常用函数:
Intent(Context packageContext,Class<?>cls),第一个参数要求提供一个启动活动的上下文,第二个参数指定想要启动的目标活动。(显式)
Intent(String action,String category),第一个参数与第二个参数分别对应AndroidManifest.XML文件中定义的acntion标签名与category标签名。
生成Intent对象后,通过调用startActivity()方法即可执行Intent。
setResult()方法接受两个参数,第一个参数用于向上一个活动返回处理结果,第二个参数把带有数据的Intent传递回去。
android:host。数据的主机名部分,比如 www.baidu.com。
android:mimeType。可以处理的数据类型。
通过Intent传递数据,需要利用Intent对象的putExtra()方法的重载。示例如下:
FirstActivity.class
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putextra("extra_data",data);
startActivity(intnet);
SecondActivity.class
Intent intent = getIntent(); //通过getintent方法获取启动SecondActivity的Intent
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
使用startActivityForResult()方法来启动Activity,返回上一个活动时会回调onActivityResult()方法,需要重写该方法。
第一个参数为使用startActivityForResult()方法启动活动时的请求码。
第二个参数为返回数据的处理结果。
第三个参数为携带返回数据的Intent。
简单实例如下:
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (requestCode == RESULT_OK) {
String returnData = data.getStringExtra("data_retun");
Log.d("FirstActivity", returnData);
}
break;
default:
}
}
接上一条,如果是点击返回键,将数据传回,在==SecondActivity==中重写onBackPressed()方法,在该方法中添加返回数据的逻辑。
Activity类中定义了7个回调方法,覆盖活动生命周期的每一个环节。
onCreate()。该方法会在活动第一次被创建的时候调用,需要在此方法中完成活动的初始化操作,比如加载布局、绑定事件。
onStart()。该方法在不可见变为可见的时候调用。
onResume()。活动准备好与用户进行交互的时候调用,此时活动一定位于返回栈的栈顶,并且处于运行状态。
onPause()。这个方法在系统准备去启动或者恢复另一个活动的时候调用。通常在此方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据。
onStop()。活动完全不可见的时候调用,与onPause()的区别在于,如果启动的新活动是一个对话框式的活动,那么onPause()方法会得到执行,onStop()不会得到执行。
onDestroy()。这个方法在活动被销毁之前调用,之后活动的状状态变为销毁状态。
onRestart()。这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动。
完整生存周期:
例子运行结果:
当一个活动进入停止状态时,可能会被回收,为了保存临时数据,需要使用到onSaveInstanceState()回调方法。
onSaveInstanceState()方法会携带一个Bundle类型的参数,它提供了一系列方法用于保存数据。
@Override
protected void onSaveInstanceState(Bundle){
super.onSaveInstanceState(outState);
String temData = "Something you just typed";
outState.putString("data_key",tempData);
}
修改方法:在
android:launchMode = "模式名"
standard是活动默认的启动模式,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置,每次都会创建该活动的一个新实例。
singleTop模式在启动活动时会检测返回栈的栈顶,如果是栈顶已经是该活动,则直接使用,不会创建新的实例,但不足之处是只检查了栈顶。
singleTask模式每次在启动该活动之前,都会在返回栈中检查是否存在该活动的实例,如果发现存在则直接使用,并把活动之上的所有活动统统出栈,如果没有则创建一个新的活动实例。
singleInstance模式下,启动的活动会启用一个新的返回栈来管理,这中模式的意义在于实现不同应用之间共享活动实例。
属性标签
属性标签
注册监听器的两种方法:
Button.setOnClickListener(new View.onClickListener){
@Override
public void onClick(View v){
//此处添加逻辑
}
}
使用实现接口的方式进行注册:implements View.OnClickListener{}
程序用于和用户交互的重要控件,允许用户在控件里输入和编辑内容。
属性标签
android:hint:提示性文本
android:maxLines:最大行数
用于在界面上展示图片的一个控件,图片通常保存在drawable目录下。
属性标签
特别注意:Android Studio资源目录中,为不同分辨率的图片建立了不同的文件夹,如果没有对应,可能运行会出错。
java.lang.RuntimeException: Canvas: trying to draw too large(?bytes) bitmap
用于在界面上显示一个进度条,表示程序正在加载一些数据。
属性标签:
该控件可以在当前的界面弹出一个对话框,这个对话框是置顶于所有界面元素之上的,一般用于提示一些非常重要的内容与警示信息。
常用方法:
AlertDialog.Builder():创建一个AlertDialog实例。
setPositiveButton():为对话框的确定按钮设置点击事件。
setNegative():为对话框设置取消按钮的点击事件。
使用实例:
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("This is Dialog");
dialog.setMessage("Something important");
dialog.setCancelable(false);
dialog.setPositiveButton("OK",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog,int which){
}
});
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.show();
ProgresDialog与AlertDialog类似,不同点在于它会在对话框中显式一个进度条,
布局与控件的关系:
线性布局:LinearLayout,这个布局会将它所有包含的控件在线性方向上依次排列。
属性标签:
相对布局:RelativeLayout通过相对定位的方式,让控件出现在布局的任何位置
属性标签:
帧布局:FrameLayout,这种布局默认所有的控件都是位于左上角。应用场景比较少。
百分比布局:为FrameLayout与Relative进行的功能扩展,需要在项目的build.gradle中添加百分比布局库的依赖。
常用控件与布局的继承关系
引入布局可以解决代码重复的问题,直接在布局文件中include即可。
属性标签:
创建自定义控件可以省去在每一个活动中,为控件添加响应事件
首先需要新建一个类,成为自定义控件。
重写相关构造函数,借助LayoutInflater的inflate()方法动态加载布局文件。第一个参数是加载的布局id,第二个参数是父布局。
随后在布局文件中通过完整的类名来引用。
Android最常用也是最难用的控件之一,解决手机屏幕空间有限的问题。
ListView中的数据需要通过适配器来传递进去,其中最常用的是ArrayAdapter。
首先通过泛型指定要适配的数据类型,然后通过构造函数把要适配的数据传入。
其构造函数第一个参数为上下文,第二个参数ListView子项布局的id,第三个参数为需要传入的数据。
最后通过调用ListView的setAdapter()方法,将构建好的适配器对象传递进去。
自定义的适配器需要继承ArrayAdapter,并且重写getView()方法。该方法在每个子项被滚动到屏幕内的时候会被调用。
ListView控件可以使用setOnItemClickListener()方法注册监听器:
ListView.setOnitemClickListener(new AdapterView.OnitemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent,View view,int position,long id){
//逻辑
}
}
利用RecyclerView编写一个简单的聊天界面:
Android中每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接受到自己所关心的广播内容,这些广播来自系统或者其它应用程序。主要有两种类型:
标准广播:完全异步执行的广播,发出之后,所有接收器几乎同时接收,效率高,无法截断。
有序广播:同步执行的广播,发出之后同一时刻只有一个广播接受器能够收到这条消息,当这个接收器中的逻辑执行完毕后,广播才会继续传递。并且前面的接收器可以截断正在传递的广播。
动态注册:新建一个继承自BroadcastReceiver类,并重写父类的onReceive(Context context,Intent intent)方法。之后调用registerReceiver()方法对接收器进行注册,传入相应的实例。最后,动态注册的广播接收器一定都要取消注册,调用unregisterReceiver()方法来实现的。PS:程序有敏感操作时,需要在AndroidManifest.xml文件中声明。
简单实例:
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver,intentFilter);
}
@Override
public void onDestroy(){
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent){
Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show();
}
}
}
静态注册:动态注册的广播接收器可以自由控制注册与注销,但前提是程序启动后才能接收,因为逻辑写在onCreate()方法中。这个时候,静态注册就能完成程序未启动时的广播接收工作。
使用AS的快捷方式创建一个广播接收器,并重写onReceive()方法,随后在AndroidManifest.xml文件中添加intent-filter过滤器,指定接收的广播action。
PS:Android8.0以后,对静态注册的广播接收器需要明确指出处理Intent的组件信息。参考资料
发送标准广播
首先需要调用Intent的构造方法构造出一条广播信息,action参数与广播接收器相对应,随后调用setComponent()方法明确指出接收该条广播的组件信息,最后调用sendBroadcast()方法发送。
简单实例:
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
intent.setComponent(new ComponentName("com.example.broadcasttest", "com.example.broadcasttest.MyBroadcastReceiver"));
sendBroadcast(intent);
发送有序广播
将sendBroadcast()方法改为sendOrderedBroadcast(intent,null),第二个参数是与权限相关的字符串。
在AndroidManifest.xml文件中,接收器的
如果需要截断广播,在onReceive()方法中调用abortBroadcast()方法。
为了能够简单地解决广播的安全问题,Android引入了本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播,核心是使用LocalBroadcastManager来对广播进行管理,并提供发送广播和注册广播接收器的方法。
PS:LocalBroadcastManager类需要导入 androidx.appcompat扩展库。
完成Android应用开发的基础知识学习,主要包括四大组件中剩下的内容提供器与服务的学习,以及Webview的使用。
学习Android系统安全机制,以及近年来Android系统相关的安全更新,做好课题背景相关研究。实现图案锁的破解。
原文:https://www.cnblogs.com/Gst-Paul/p/12501248.html