赞
踩
Android is an open source, Linux-based software stack created for a wide array of devices and form factors.
Android 是一个开源的,基于Linux的用于针对不同尺寸的移动设备创建界面的软件堆栈。
系统架构:
Application层: 也就是应用层,不仅包括通话短信联系人这种系统级的应用,还包括用户自己安装的一些第三方应用
Framework层:这一层大部分用Java写的,包括系统服务和四大组件
Library层:这一层大部分都是C/C++写的,主要是虚拟机,还有一些三方库比如SQLite, WebKit
HAL层:硬件抽象层,
Linux内核层:包含Linux内核和一些驱动,比如说蓝牙驱动,Camera驱动等等,这个Binder驱动也是在这一层
The Android platform provides a framework API that applications can use to interact with the underlying Android system.
The framework API consists of:
Android platform 提供了一个让应用可以和底层Android系统进行交互的API框架。
Updates to the framework API are designed so that the new API remains compatible with earlier versions of the API.
two case:
更新API框架被设计以便于新老API可以兼容。
有两种情况:
API Level ≠ Android Platform Version
minSdkVersion:最小的API Level。
targetSdkVersion:目标SDK版本,建议使用最新。
compileSdkVersion:编译工程的SDK版本。不应该比targetSdkVersion低。
maxSdkVersion:最大的API Level。
A layout resource defines the architecture for the UI in an Activity or a component of a UI
布局资源定义了Activity或UI组件中UI的体系结构
The View class represents the basic building block for UI components.
There are many specialized subclasses of views that act as controls or are capable of displaying text, images, or other content.
View类代表UI组件的基本构建块。
有许多专用的视图子类可以充当控件或能够显示文本,图像或其他内容。
View Class的通用属性:
IDs:
“@+id/idName” – 例如 @+id/mybutton
“@id/idName” – 例如 @id/mybutton
android:layout_height 和 android:layout_width
尺寸值:
基于屏幕物理尺寸的单位:in,mm,pt。1 in = 25.4 mm = 72 pt。他们无法在所有设备上正常运行。
基于像素:Pixel(像素),Resolution(分辨率),Pixel Density:(像素密度 dpi)
px,dp,sp。px = dp * (dpi / 160)
match_parent:该视图希望与父视图一样大(减去父视图的填充,如果有的话)
wrap_content:视图要足够大以包围其内容(考虑其自身的填充)
Padding
它定义了视图边缘和视图内容之间的空间
android:paddingTop 上
android:paddingBottom 下
android:paddingLeft 左
android:paddingRight 右
android:paddingStart 基于ui设置
andorid:paddingEnd 基于ui设置
View Group Class包含其他视图的特殊视图
属性:
属性:
理解活动的生命周期:
onCreate()
The primary information contained in an Intent can be classified into two kinds:
ACTION_VIEW:
当您掌握活动可以向用户显示的某些信息(例如,要在图库应用程序中查看的照片或要在地图应用程序中查看的地址)时,可以将其与startActivity()一起使用。
ACTION_ SEND
也称为共享意图,当您拥有一些用户可以通过其他应用程序(例如电子邮件应用程序或社交共享应用程序)共享的数据时,可以将其用于带有startActivity()的意图中。
ACTION_ DIAL
此操作拨打数据指定的号码。这显示了带有拨号号码的UI,允许用户显式发起呼叫。
ACTION_MAIN
此操作将活动指示为应用程序的主要入口点。它不希望接收数据。
指明Action:
1.
2.
管理task的栈。栈中的Activity按照他们被打开的顺序依次存放。一般我们只从栈顶添加或移除Activity,栈中的Activity顺序是固定的。也可通过launchMode和Intent的Flags改变栈中Activity的顺序。
例子:
总结:Task(任务)是Activity的容器或者集合,通过Back栈来管理。而栈中Activity的顺序是按照启动Activity的先后来决定的,但是我们可以通过launchMode和Flags来改变顺序。
standard(默认启动模式)
每次启动一个Activity都会创建一个新的实例,加入到Task中。
如果是跨应用:在Android5.0以前,被跨进程启动的Activity,会加入到启动它的应用的Task中;而在Android5.0之后,会创建一个新的Task,然后加入。
singleTop(栈顶复用模式)
即每次启动一个Activity会判断当前Task栈顶是不是该Activity的实例,如果是,则调用onNewIntent()重新启动,否则创建新的实例并加入Task。
这里跨进程的情形同standard。(会创建新的实例,但Android5.0前后是不同的)
singleTask(栈内复用模式)
如果该栈中有其实例(没有栈顶的限制条件),则不会重新创建实例,而是将之前的Activity移除,将其置于栈顶。这里具体分析跨进程启动的问题,假设在该启动模式下,跨进程启动Activity A,如果被启动的应用A不存在Task A,则会先创建Task A;如果存在Task A,但没有该Activity A 的实例,则将A加入D到Task A中。如果存在Activity A实例,则将A上面的Activity移除,使其位于栈顶。
SingleInstance(单一实例模式)
整个手机系统里只有一个实例存在。
对于声明为SingleInstance的Activity,它所在的栈中不会再放入Activity,也就是这个Task中只有它一个实例。而通过它启动的Activity也会放入其他Task中,因此可以保持单一实例。
示例
<activity android:name="com.will.testdemo.launchmode.A"
android:launchMode="standard">
</activity
除了Manifes中,还可以在startActivity的时候为iIntent添加一个flag来改变Activity与Task的关联方式。这里介绍集中常用的Flags。
FLAG_ACTIVITY_NEW_TASK
无论是否跨进程,每次启动一个Activity,都会新建一个Task,并放入。
FLAG_ACITVITY-SINGLE_TOP
同LaunchMode中的singleTop
FLAG_ACTIVITY_CLEAR_TOP
同LaunchMode的singleTask
示例:
Intent intent = new Intent(MainActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//or intent.addFlags();
startActivity(intent);
taskAffinity,可以翻译为任务相关性。这个参数标识了一个 Activity 所需要的任务栈的名字,默认情况下,所有 Activity 所需的任务栈的名字为应用的包名,当 Activity 设置了 taskAffinity 属性,那么这个 Activity 在被创建时就会运行在和 taskAffinity 名字相同的任务栈中,如果没有,则新建 taskAffinity 指定的任务栈,并将 Activity 放入该栈中。另外,taskAffinity 属性主要和 singleTask 或者 allowTaskReparenting 属性配对使用,在其他情况下没有意义。
默认情况下, 一个Task在后台过了很长时间后,系统会将该Task中除最底层的Activity清除掉,在重新回到前台后,最底层的Activity会得到恢复。
而Android提供了方法,可以改变这种默认的状态,即在Manifest中的属性中进行修改。
常用属性:
android:inputType="none"//输入普通字符 android:inputType="text"//输入普通字符 android:inputType="textCapCharacters"//输入普通字符 android:inputType="textCapWords"//单词首字母大小 android:inputType="textCapSentences"//仅第一个字母大小 android:inputType="textAutoCorrect"//前两个自动完成 android:inputType="textAutoComplete"//前两个自动完成 android:inputType="textMultiLine"//多行输入 android:inputType="textImeMultiLine"//输入法多行(不一定支持) android:inputType="textNoSuggestions"//不提示 android:inputType="textUri"//URI格式 android:inputType="textEmailAddress"//电子邮件地址格式 android:inputType="textEmailSubject"//邮件主题格式 android:inputType="textShortMessage"//短消息格式 android:inputType="textLongMessage"//长消息格式 android:inputType="textPersonName"//人名格式 android:inputType="textPostalAddress"//邮政格式 android:inputType="textPassword"//密码格式 android:inputType="textVisiblePassword"//密码可见格式 android:inputType="textWebEditText"//作为网页表单的文本格式 android:inputType="textFilter"//文本筛选格式 android:inputType="textPhonetic"//拼音输入格式 //数值类型 android:inputType="number"//数字格式 android:inputType="numberSigned"//有符号数字格式 android:inputType="numberDecimal"//可以带小数点的浮点格式 android:inputType="phone"//拨号键盘 android:inputType="datetime"//日期+时间格式 android:inputType="date"//日期键盘 android:inputType="time"//时间键盘
会话包含三个部分:
创建:
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Alert");
builder.setMessage("Content area");
AlertDialog dialog = builder.create();
设置属性:
1.添加按钮:(button)
//能够使用这个按钮去接受或继续这个Action builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //todo } }); //能够使用这个按钮去取消这个Action builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //todo } }); //不操作 builder.setNeutralButton("Remind me later", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //todo } });
2.添加列表(list)
添加传统的单选清单:
添加持久性单选列表(单选按钮)
3.添加选择器(picker)
添加 time picker:
//构造器
public TimePickerDialog(Context context,
TimePickerDialog.OnTimeSetListener listener,
int hourOfDay,
int minute,
boolean is24HourView);
//context 父类context
//listener 监听器
//hourOfDay 初始化小时
//minute 初试化分钟
//is24HourView 24小时制
添加 date picker
例:
android:src 用于展示ImageView的图片
android:contentDescription 图片的描述
Bitmap File:
支持三种格式:.png .jpg .gif
可在目录res/drawable下添加
示例:
位置:res/drawable/filename.png
设置:
Java:
imageView.setImageResource(R.drawable.image01);
XML:
android:src="@drawable/image01"
Drawable Class:
展示静态图像。
1.从resource images 中创建:
或
Vector drawable:
VectorDrawable是在XML文件中定义为一组点,线和曲线及其关联颜色信息的矢量图形。
常用属性:
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf //文本基线,基于文本对齐
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
示例:
总结:
角度定位指的是可以用一个角度和一个距离来约束两个空间的中心。
例子:
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintCircle="@+id/TextView1"
app:layout_constraintCircleAngle="120"
app:layout_constraintCircleRadius="150dp" />
margin:
ConstraintLayout的边距常用属性如下:
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
注意:控件在ConstraintLayout里面要实现margin,必须先约束该控件在ConstraintLayout里的位置。
示例:
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp" />
</android.support.constraint.ConstraintLayout>
如果在别的布局里,TextView1的位置应该是距离边框的左边和上面有一个10dp的边距,但是在ConstraintLayout里,是不生效的,因为没有约束TextView1在布局里的位置。正确的写法如下:
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
把TextView1的左边和上边约束到parent的左边和上边,这样margin就会生效,效果如下:
在使用margin的时候要注意两点:
控件必须在布局里约束一个相对位置
margin只能大于等于0
goneMargin:
goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值,属性如下:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
举个例子:
假设TextView2的左边约束在TextView1的右边,并给TextView2设一个app:layout_goneMarginLeft=“10dp”,代码如下:
<android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/TextView1" .../> <TextView android:id="@+id/TextView2" ... app:layout_constraintLeft_toRightOf="@+id/TextView1" app:layout_goneMarginLeft="10dp" /> </android.support.constraint.ConstraintLayout>
效果如下,TextView2在TextView1的右边,且没有边距。
这个时候把TextView1的可见性设为gone,效果如下:
TextView1消失后,TextView2有一个距离左边10dp的边距。
在RelativeLayout中,把控件放在布局中间的方法是把layout_centerInParent设为true,而在ConstraintLayout中的写法是:
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
意思是把控件的上下左右约束在布局的上下左右,这样就能把控件放在布局的中间了。同理RelativeLayout中的水平居中layout_centerHorizontal相当于在ConstraintLayout约束控件的左右为parent的左右;RelativeLayout中的垂直居中layout_centerVertical相当于在ConstraintLayout约束控件的上下为parent的上下。
由于ConstraintLayout中的居中已经为控件约束了一个相对位置,所以可以使用margin,如下所示:
<TextView
android:id="@+id/TextView1"
...
android:layout_marginLeft="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
效果如下:
一个app必须在manifest中用标签来声明权限。
如果您的应用在其清单中列出了常规权限(即,不会对用户的隐私或设备的操作造成太大风险的权限),则系统会自动将这些权限授予您的应用。 如果您的应用在清单中列出了危险的权限(即可能会影响用户隐私或设备正常操作的权限),例如上面的SEND_SMS权限,则用户必须明确同意授予这些权限。 提供有关正常和危险权限的更多信息。
(1)Normal 权限被声明为Normal级别,任何应用都可以申请,在安装应用时,不会直接提示给用户,点击全部才会展示。 (2)Dangerous 权限被声明为Dangerous级别,任何应用都可以申请,在安装应用时,会直接提示给用户。 (3)Signature 权限被声明为Signature级别,只有和该apk(定义了这个权限的apk)用相同的私钥签名的应用才可以申请该权限。 frameworks/base/core/res/AndroidManifest.xml声明的权限为Signature级别,那么只有Android官方使用相同私钥签名的应用才可以申请该权限。 (4)SignatureOrSystem 权限被声明为SignatureOrSystem级别,有两种应用可以申请该权限。 1)和该apk(定义了这个权限的apk)用相同的私钥签名的应用 2)在/system/app目录下的应用
1.如果设备运行的是Android 6.0(API级别23)或更高版本:
2.如果设备运行的是Android 5,1.1(APl级别22)或更低版本,或者在任何版本的Android上运行时,应用程序的targetSdkVersion为22或更低版本,系统会在安装时自动要求用户授予您的应用程序所有危险权限。
可以在manifest中使用标签声明硬件功能。
<uses-feature android:name="android.hardware.camera" android:required="false"/>
如果request=false,允许将您的应用安装在不具有该功能的设备上。然后,您必须在运行时通过调用PackageManager.hasSystemFeature()检查当前设备是否具有该功能,并在该功能不可用时禁用它。
如果没有声明标签,则当Google Play看到您的应用请求相应的权限时,它会假定您的应用需要此功能。因此,它会从没有该功能的设备中过滤出您的应用,就像您声明了 标记中的android:required =“ true”。
所以说permissiongroup只是一个逻辑分组,作用也只有显示应用程序权限给用户看的。
当然需要额外说明的是, 并不是所有的Permission都有PermissionGroup, 有的可能没有分组。 这些没有分组的Permission也会自己指定label, 以便告知用户这个权限的作用。
1.在manifest添加权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="string"
android:sharedUserId="string"
android:sharedUserLabel="string resource"
android:versionCode="integer"
android:versionName="string"
android:installLocation=["auto" | "internalOnly" | "preferExternal"] >
<uses-permission android:name="string"
android:maxSdkVersion="integer" />
</manifest>
2.检查权限(如果是dangerous permission)
if(ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED){
//未授权
}else{
//授权
}
3.请求权限
if(ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED){
//未授权,请求权限
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.READ_CONTACTS},1);
}else{
//已授权
}
4.处理权限请求结果
@Override
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults){
switch(requsetCode){
case 1:{
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
//已授权操作
}else{
//未授权操作
}
return;
}
//其他case情况
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。