安卓开发
安卓开发
创建第一个安卓程序

包名不可以有中文名字

Create project launcher icon //是否创建启动的图标

下载夜神模拟器去运行安装程序。
在cmd中输入adb查看是否可以访问到该程序,如果没有需要添加环境变量。
在系统中添加adb程序路径即可
然后在命令终端输入以下命令,即可以使eclipse与夜神模拟器建立链接。
adb connect 127.0.0.1:62001 //62001是夜神模拟器暴露的端口。
如果链接失败要重启adb
adb kill-server
adb start-server
安卓工程文夹介绍

src:存放Java代码的,有包 有文件。
gen:存放自动生成的文件,关心是R.java。程序页面,按键,文本等控件的ID。
Android 4.4和Android Private Libraries是安卓支持的一些库。
assets:存放一些资源,配置文件,图片等
bin:编译后会生成的文件,包括我们关心的安装包(.apk文件)
libs:依赖库
res:
drawable开头的文件:存放app程序要用到的一些图片
layout:存放布局文件的文件夹,一般一个activit(安卓页面)对应一个布局。
menu和values:存放一些参数,或者自定义控制文件
AndroidManifest.xml:APP的配置
权限:网络访问权限,名片夹访问权限、相机访问权限。
目标机器SDK版本
APP名字
APP图标
配置第一个被加载,启动页面。
安卓APP的启动过程
-
Launcher进程不断的检测,用户的手按在哪个APP上面。
-
当用户触摸到某个APP的时候,最先执行的时候Java里面的AndroidManifest.xml的文件,该文夹会多APP做出相应的配置(权限,目标平台版本...)
在这个文件中会决定打开安卓APP第一个运行的是哪个页面。

- 此时在src中找到相应的文件。

可以看到MainActivity继承于Activity,说明MainActivity也是一个页面。onCreate相当于一个入口,会被自动的拿来运行。
super.onCreate(savedInstanceState); //执行父类的onCreate方法,创造一个空白页。
setContentView(R.layout.activity_main); //把当前代码和R.layout.activity_main相关联起来
- 打开R.layout.activity_main代码,该文件中存放的是组件的ID号,通过ID号使刚刚创建的空白页面与activity_main文件相关联。

安卓的布局
安卓是有六大布局,布局和布局之间继承的关系。

作为非安卓开发人员,我们常用到的是相对布局。

可以看到,在<RelativeLayout> <\RelativeLayout >之间就是布局区域的大小,我们的文本框和按键都是在布局内添加的。
实现安卓APP显示一个美女
这是该APP的布局,其中layout_width和layout_height设置该布局的宽和高。match_parent表示全屏大小。
android:background="@drawable/ad" 表示引入的照片。@drawable 表示照片在drawable文件夹下。
<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="@drawable/ad"
tools:context=".MainActivity" >
</RelativeLayout>
注意 : 所有的照片都放在res文件夹下的drawable文件夹下,照片的命名必须是由小写字母a-z和0-9组成。必须用小写字母作为照片的开头。照片的格式位png格式。

安卓APP实现两个美女
实现显示两个美女,首先考虑的是布局。
要有一个总体的大的布局包含整个手机屏幕,然后两个小的布局分别占手机屏幕的一半。
<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="@drawable/ad"
tools:context=".MainActivity" >
<RelativeLayout
android:id="@+id/gril1"
android:layout_width="match_parent"
android:layout_height="350dp"
android:background="@drawable/ad">
</RelativeLayout>
<RelativeLayout
android:layout_below="@id/gril1"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="@drawable/ad">
</RelativeLayout>
</RelativeLayout>
android:id="@+id/gril1" 是个生成一个布局ID(此时会在gen/id的文件夹下生成gril1).
android:layout_below="@id/gril1" 因为我们采用的是相对布局,所以我们第二张照片要显示在第一张的下面,使用第一张照片的布局id来找到第一张的布局。layout_below表示在第一个布局的下面。
相对布局RelativeLayout常用空间属性
1.相对于父控件
android:layout_alignParentTop 控件的顶部与父控件的顶部对齐;
android:layout_alignParentBottom 控件的底部与父控件的底部对齐;
android:layout_alignParentLeft 控件的左部与父控件的左部对齐;
android:layout_alignParentRight 控件的右部与父控件的右部对齐;

所有被包含的控件都是子控件。
2.相对给定ID控件
android:layout_above 控件的底部置于给定ID的控件之上;
android:layout_below 控件的底部置于给定ID的控件之下;
android:layout_toLeftOf 控件的右边缘与给定ID的控件左边缘对齐;
android:layout_toRightOf 控件的左边缘与给定ID的控件右边缘对齐;
android:layout_alignBaseline 控件的底部与给定ID的底部对齐;
android:layout_alignTop 控件的顶部边缘与给定ID的顶部边缘对齐;
android:layout_alignBottom 控件的底部边缘与给定ID的底部边缘对齐;
android:layout_alignLeft 控件的左边缘与给定ID的左边缘对齐;
android:layout_alignRight 控件的右边缘与给定ID的右边缘对齐;
3.居中
android:layout_centerHorizontal 水平居中;
android:layout_centerVertical 垂直居中;
android:layout_centerInParent 父控件的中央;
基础控件
Button,TextView,EditText,ImageView
Button:是按键控件
TextView:是一个文本框
EditText:是一个输入框
ImageView:插入图片
<ImageView
android:id="@+id/pic"
android:src="@drawable/test3"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignBottom="@id/use"
/>
padding和margin
margin: 属性用于设置视图之外的空间。
设置控件的上下左右各个方向上的边距
比如:
<TextView
android:id="@+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/use" //在id是use控件的下方
android:layout_marginTop="20dp" //设置上边为20dp
android:layout_marginLeft="20dp" //设置左边边距为20dp
android:layout_marginRight="10dp" //设置右边边距为10dp
android:text="密码"
android:textColor="#ffffff"
android:textSize="20dp" />
padding:属性用于设置内容和部件元素的边界之间的空间。
例如 按键中的文字
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/password"
android:layout_toRightOf="@id/button1"
android:layout_marginLeft="50dp"
android:paddingRight="50dp" //比如按键中的文字,基于按键的右边框移动50dp
android:text="取消"/>
android:inputType="textPassword" //可以使文本框中用户输入的数据变成密文。
按键的美化
(108条消息) Android 圆角按钮的实现_android 按钮圆角_tracydragonlxy的博客-CSDN博客
线性布局
可以设置各个组件的排列方式,模式是横向的。
可以通过orientation进行竖向排列
<LinearLayout 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:orientation="vertical" //各个组件竖向排列
tools:context=".MainActivity" >
</LinearLayout>
线性布局之Weight
weight属性用来等比例地划分区域
最简单的用法,要等比例划分谁,谁为0,wight按比例即可
<LinearLayout
android:layout_weight="5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#0000ff"
android:orientation="vertical" //将控件按竖向排列
>
<EditText
android:layout_weight="1" //权重为1
android:layout_width="match_parent"
android:layout_height="0dp" //因为控件是按竖向排列的,将高度设置为0,权重设置为1,下面的组件权重也是1,相当于1:1平分
/>
<EditText
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp"
/>
</LinearLayout>
线性布局之gravity
gravity常用于微调
<LinearLayout
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#00ff00"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center" //在组件所包含需要的正中央显示
android:layout_weight="1"
android:text="账号"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:text="密码"
/>
</LinearLayout>
线性布局之divider不常用
divider为linear layout设置分割线的图片
安卓开发之响应第一种方式
在xml中设置按键的onClick绑定的函数
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="buttonBeCliecked" //响应函数是buttonBeCliecked
android:text="响应" //该函数使用java写的
/>
在Eclipse上使用logcat进行调试
(108条消息) Eclipse上Logcat不显示日志的解决办法和注意事项_eclipse控制台日志刷没了怎么办_anod的博客-CSDN博客
buttonBeCliecked函数
public void buttonBeCliecked(View v)
{
//System.out.println(v.getId());
switch (v.getId()){
case R.id.button1:
Toast.makeText(this, "按键一被按下", 0).show(); //当用户按下按键一时,会在app中显示“按键一被按下”
break;
case R.id.button2:
Toast.makeText(this, "按键二被按下", 0).show();
break;
}
}
安卓开发之响应第二种方式自定义类
关于监听器:监听器是一个存在于View类下的接口,一般以On******Llistener命名,实现该接口需要复写相应的on****(View v)方法(如onClick(View v))。
OnClickListener接口:该接口处理的是点击事件。在触摸模式下,是在某个View上按下并抬起的组合动作,而在键盘模式下,是某个View获得焦点后点击确定键或者按下轨迹球事件。
public class MainActivity extends Activity {
//创建两个按键对象
Button btn1 ;
Button btn2 ;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//把xml里面的button1和我们创建的btn1链接联系
btn1 = (Button) findViewById(id.button1);
btn2 = (Button) findViewById(id.button2);
btn1.setOnClickListener(new MyClieckHandler());
btn1.setOnClickListener(new MyClieckHandler());
}
}
MyClieckHandler类
class MyClieckHandler implements View.OnClickListener
{
public void onClick(View v) {
switch (v.getId()){
case R.id.button1:
System.out.println("按键一被按下");
break;
case R.id.button2:
System.out.println("按键二被按下");
break;
}
}
}
View.OnClickListener是一个接口,MyClieckHandler类用来实现接口里面的方法。
总体步骤
1、绑定 局部变量button和xml中的button, findViewById方法

2、实现接口类,在类中实现onclicked方法,写业务代码

3、为1,2两部做的准备进行绑定。使得按键被按下后执行你写的业务代码

安卓开发之响应第三种方式匿名内部类
和自定义接口类的实现方式相似。
public class MainActivity extends Activity {
Button btn1 ;
Button btn2 ;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//把xml里面的button1和我们创建的btn1链接联系
btn1 = (Button) findViewById(id.button1);
btn2 = (Button) findViewById(id.button2);
//实现内部类
View.OnClickListener test1 = new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "按键二被按下", 0).show();
}
};
View.OnClickListener test2 = new View.OnClickListener () {
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "按键一被按下", 0).show();
}
};
//绑定触发事件
btn1.setOnClickListener(test1);
btn2.setOnClickListener(test2);
}
}
抽象类补充
抽象类不可以被实例化,只可以被子例化
例如
//实现内部类
View.OnClickListener test1 = new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "按键二被按下", 0).show();
}
};
View.OnClickListener test1 = new View.OnClickListener()
左边是 new View.OnClickListener()是创建该抽象类的一个子类。
右边View.OnClickListener test1是创建一个对象,但是不是抽象类的对象,而是抽象类子类的对象。
安卓开发之响应第四种方式 Activity
public class MainActivity extends Activity implements View.OnClickListener{
Button btn1 ;
Button btn2 ;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//把xml里面的button1和我们创建的btn1链接联系
btn1 = (Button) findViewById(id.button1);
btn2 = (Button) findViewById(id.button2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()){
case R.id.button1:
Toast.makeText(this, "按键二被按下", 0).show();
break;
case R.id.button2:
Toast.makeText(this, "按键一被按下", 0).show();
break;
}
}
}
为安卓添加多个页面
如何添加一个页面

右键点击src,点击other。

点击Android,选择Android activity

选择空白页面即可

页面之间如何跳转
public void onClick(View v) {
//设置要跳转的页面
Intent intent = new Intent(this, ThreadActivity.class);
//跳转
startActivity(intent);
}
页面跳转传参
实现效果,在页面一向页面二跳转时传入参数。
//传入参数
intent_2.putExtra("徐博正", "很帅");
其中putExtra是方法重载,可以传递各种同组合的参数。
该传参方法类似于键值对
接收方法通过,前面的字段对比,获得想要的数据。
这是接收页面的代码
//调用SecondActivity类中自带的Intent
Intent intent = this.getIntent();
data = intent.getStringExtra("徐博正");
Toast.makeText(this, data, 10).show();
data的值是 “很帅”,比对的依据是 “徐博正”。
页面跳转传参的第二种方法
使用bundle类来进行传参
public void onClick(View v) {
//intent去设置要跳转的页面
Intent intent_2 = new Intent(this, SecondActivity.class);
Intent intent_3 = new Intent(this, ThreadActivity.class);
switch (v.getId())
{
case R.id.button1:
//传入参数
Bundle bundle = new Bundle(); //实例化一个对象
bundle.putString("徐博正", "太牛了把");
bundle.putString("帅哥", "大神");
intent_2.putExtras(bundle); //将bundle对象传入给第二个页面。
//跳转
startActivity(intent_2);
break;
case R.id.button2:
//跳转
startActivity(intent_3);
break;
}
}
}
//调用SecondActivity类中自带的Intent
Intent intent = this.getIntent();
Bundle b = intent.getExtras();
data1 = b.getString("徐博正");
data2 = b.getString("帅哥");
第二个页面调用intent.getExtras()方法来获取到传过来的bundle并解析里面的数据。
页面的自动跳转
当我们打开一个安卓app的时候,有的时候会先出现几秒的广告,然后在进入控制页面。
使用页面的自动跳转就可以实现该效果。
在实现页面跳转的过程中,肯定会用到sleep函数,切记,不要再UI线程中去sleep,UI会被sleep暂停刷新,应该另起一个线程。
//要在新线程中去sleep,另外启动一个线程,在三秒后启动一个新页面,不要再UI线程中去sleep。UI被sleep暂停刷新
//创建一个线程,实例化一个对象。
Thread t = new Thread(new Runnable() {
//实现该线程要实现的函数
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//跳转
Intent intent_2 = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent_2);
}
});
//启动线程
t.start();
Activity 生命周期

安卓之socket编程
服务端代码
和之前用C语言写socket一样,都是先暴露端口号和IP的地址,然后accept等待客户端进行链接。
//1.创建套接字,设置Ip和端口号
try {
ServerSocket socke = new ServerSocket(8801);
System.out.println("socket 套接字创建成功 等待链接");
//获取链接通道
Socket con = socke.accept();
System.out.println("有客户链接");
//获取输入流
InputStream in = con.getInputStream();
//读取数据,返回值是读取数据的长度
len = in.read(data);
//输出数据
System.out.println("读到消息+ "+new String(data, 0, len));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
new String(data, 0, len)表示的是,把byte类型的data数组,转换字符串输出,0表示从第0个元素开始输出,输出到第len个停止。
使用线程的方式,实现多方链接。
匿名内部类访问的局部变量必须要用final修饰

在上面代码中,a是局部变量,Runnable是一个匿名内部类,如果在匿名内部类中想要用到a,需要在a的前面加入final修饰词。
多方链接的代码
public class Test {
public static void main(String[] args) {
//1.创建套接字,设置Ip和端口号
try {
ServerSocket socke = new ServerSocket(8801);
System.out.println("socket 套接字创建成功 等待链接");
while(true){
//获取链接通道
final Socket con = socke.accept();
System.out.println("有客户链接");
//创建一个线程
new Thread(new Runnable() {
public void run() {
//获取输入流
InputStream in;
try {
int len = 0;
byte []data = new byte[100];
in = con.getInputStream();
//读取数据,返回值是读取数据的长度
len = in.read(data);
//输出数据
System.out.println("读到消息+ "+new String(data, 0, len));
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端代码
public class Test {
public static void main(String[] args) {
byte []buf = new byte[128];
try {
//链接到服务端的ip地址和端口号
Socket client = new Socket("192.168.43.223", 8899);
//获得数据发送通道
OutputStream out = client.getOutputStream();
Scanner scanf = new Scanner(System.in);
String message = scanf.nextLine();
out.write(message.getBytes());
//获得数据接收通道
InputStream put = client.getInputStream();
int len = put.read(buf);
System.out.println("收到数据 "+new String(buf, 0, len));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
javaApp 之 scoket客户端
注意:用javaApp向服务端发送数据的时候,socket需要单独启动一个线程来执行,不可以在main函数所在线程来执行。
这是检测到用户按键后所执行的代码。
Thread thread = new Thread(new Runnable() {
public void run() {
netWork();
}
});
thread.start();
即:重新启动一个线程,在执行netWork函数。netWork函数内容
public void netWork()
{
try {
Socket socket = new Socket("192.168.43.223", 8899);
OutputStream out = socket.getOutputStream();
String message = "xubozheng";
out.write(message.getBytes());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
非UI线程修改控件内容问题
//按下APP上的按键以后,就会执行下面的函数
public void TestFun(View v)
{
new Thread(new Runnable() {
public void run() {
//按下按键,实现文本框数据的刷新
for (int i = 0; i < 10; i++) {
//设置text文本框的内容
text.setText("xubozheg"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
该代码的逻辑是,先创建一个线程,该线程每隔秒钟刷新一次文本框的内容。
但是,此代码运行会导致程序的奔溃。
原因是因为,非UI线程不可以修改UI页面下的控件的内容。
解决问题
解决这个问题要引入handler类,在UI主线程中,初始化一个handler类的对象,并且设置好收到消息后的处理方法。
由上面问题我们可以知道,非UI主主线程无法修改UI主线程中的控件内容。
于是我们用到了handler类,该类的作用就是,用来接收其他线程的消息,并将收到的消息可以显示在相应的控件上。
handler 像是UI主线程家里的电话,接到电话后,去处理一些其他线程无法处理的事件。
主要,导入包的时候,选择第一个包。

新创建的线程,一秒发一个message,用于之UI线程中控件的内容显示。
public void TestFun(View v)
{
new Thread(new Runnable() {
public void run() {
//按下按键,实现文本框数据的刷新
for (int i = 10; i > -1; i--) {
try {
//定义message里面的内容
Message message = new Message();
message.what = i;
//把message传给UI线程
h.sendMessage(message);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
在主UI线程中,handler负责就收消息,并将其显示在相应的控件位置处。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//handler 像是UI主线程家里的电话,接到电话后,去处理一些其他线程无法处理的事件。
h = new Handler(){
//区分事件的类型
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
text.setText(msg.what+"s");
}
};
text = (TextView) findViewById(R.id.text);
}
安卓webView
可以参考以下博文
https://blog.csdn.net/weixin_40438421/article/details/85700109
使用editText控件,回车不换行问题解决
https://blog.csdn.net/sy755754582/article/details/54099272
设置webView访问网页的时候,会需要开启网络权限。
1.在AndroidManifest.xml文件中,找到permissions选项。

2.点解add,原则Uses Permission选项。

3.在右侧Name栏中,找到带INSETNET字段数据后,保存即可。
具体使用代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
web = (WebView) findViewById(R.id.webView);
ed = (EditText) findViewById(id.ed);
//系统默认会通过手机浏览器打开网页,为了能够直接通过WebView显示网页,则必须设置
web.setWebViewClient(new WebViewClient());
//为了editText组件输入后,回车不换行
ed.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
//获取组件中输入的数据,并转换成字符串
String url = ed.getText().toString();
//访问该网页
web.loadUrl(url);
return (event.getKeyCode() == KeyEvent.KEYCODE_ENTER);
}
});
}

浙公网安备 33010602011771号