5月31号adb命令及基本的Android开发知识
1、adb命令:安卓调试桥
adb devices:查看连接的手机设备
adb kill-server:杀死adb调试桥
adb start-server:启动adb的调试桥
adb install 包名:安装软件
adb uninstall 包名:卸载软件
adb help:最好不要说
adb version:看版本
adb reboot:重启
adb shell wm size:查看分辨率
adb logcat:查看日志
2、安卓工程结构
src:java源码
onCreate:应用程序界面被创建被调用的方法
setContentView:设置应用程序显示的ui
res:资源文件
drawable放置图片:l->m->h->xh->xxh(有小到大)
layout:用xml编写的布局
menu:菜单文件夹
values:string包名(能看到的)
AndroidManifest.xml:清单文件,配置应用程序的版本、图标、名称等重要信息
gen目录:自动生成的文件夹,资源文件
libs三方jar包
Android dependencies:开发依赖的jar包
bin:二进制文件
3、第一个Android程序:
(1)布局:android:id="@+id/button1":声明按钮id,加入到R文件
(2)src写代码
(3)找到控件
(4)设置点击事件,或者获取权限
6月11号常见的布局
EditText:输入框
TextView:显示框
1、常见的布局:
(1)线性布局:LinearLayout(所有控件排成一条线)
orientation(朝向):vertical垂直,horizontal水平
layout_width(宽度、height高度):fill_parant、match填充父窗体,wrap_contant包裹里边内容(比如文字)
layout_weight:比例值,首先将layout_width设置为0px,在赋值1或者其他(例如两个按钮值1,3则为25%和75%)
gravity:设置默认排列位置,center_horizontal为水平居中
综合案例,计算器(calc.xml文件)
(2)相对布局:RelativeLayout(相对于控件的位置)
设置boolean的属性:
centerHorizontal:水平居中
centerVertical:垂直居中
centerInParent:整体居中
设置其他UI组件id的属性(@id/)
toRightOf:ID组件的右侧
toLeftOf:ID组件的左侧
above:ID组件的上部
below:ID组件的下部
二者都有的:
alignTop/alignParentTop:顶(垂直方向)
alignBottom/alignParentBottom:底(垂直方向)
alignRight/alignParentRight:右(水平方向)
alignLeft/alignParentLeft:左(水平方向)
示例,demo02_relativelayout.xml相对布局练习
(3)帧布局:FrameLayout(类似于div一层一层的)
从上到下依次展示
gravity:组件的位置
background:颜色#000000
示例,demo03_framelayout.xml
(4)表格布局:TableLayout(与网页中table表单类似)
TableRow:某一行(与线性布局类似)
示例,demo06_tablelayout.xml
(5)绝对布局:AbsoluteLayout(绝对布局已经过时,不应使用或少使用)
有时候会用:机顶盒开发
layout_x
layout_y
示例,demo05_absolutelayout.xml
单位:px与dp(px是绝对的,dp是相对的),一般用dp
6月14号java基本扩展
1、监听器实现某一个接口(OnClickListener)
(1)接口不能直接new需要创建一个类实现接口:
class ButtonClickListener implements OnClickListener
login.setOnClickListener(new ButtonClickListener);
(2)利用匿名内部类:
login.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {//实现的具体逻辑} });
(3)直接当前类实现OnClickListener,
当前类implements OnClickListener
login.setOnClickListener(this);
示例:MainActivity.java
2、直接调用方法:
(1)在xml中定义按钮android:onClick="click":click为方法名
(2)在MainActivity.java中添加方法click
public void click(View v) :注意,一定要有View v,否则会崩溃
3、字符串的处理:
(1)TextUtils.isEmpty:排空
if (TextUtils.isEmpty(usernameString)||TextUtils.isEmpty(passwordString)) {
//处理逻辑
return;}
(2).trim():该方法可以去除首尾的空格
4、输出日志及打印信息(Android中logcat或ddms):
Log.v(tag, "我是verbose级别的日志");
Log.d(tag, "我是debug级别的日志");
Log.i(tag, "我是info级别的日志");
Log.w(tag, "我是警告级别的日志");
Log.e(tag, "我是error级别的日志");
Log.wtf(tag, "我是重大异常级别的日志");
System.out.println("哈哈哈哈哈哈");
5、发短信(权限android.permission.SEND_SMS):
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage("10086", null, usernameString+"---"+passwordString, null, null);
6月14号常见的控件及监听器
通用:layout_marginLeft:距离左侧距离:xx dp
1、Button按钮:
监听器:OnClickListener
2、EditText文本输入框:
hint:文本输入框的默认值
inputType:输入框的类型(默认为text),密码展示为textPassword
3、TextView文本展示:
4、ImageView图片:
android:src="@drawable/app":文件的引用路径res中
5、CheckBox单按钮:
android:text="记住密码"
java中可以判断是否点击isChecked()
监听器:OnCheckedChangeListener:
onCheckedChanged:CheckBox点击事件
6、SeekBar进度条:
android:max="100":进度条的最大值,必须有
监听器OnSeekBarChangeListener:
onStopTrackingTouch://停止拖动调用的方法
onStartTrackingTouch://开始拖动调用的方法
onProgressChanged://在拖动过程中调用的方法
7、View一条灰色的分割线:
android:background="#11000000"//8位有两位表示灰度值
8、RadioGroup单选按钮:
RadioButton中有id值然后可以判断哪个点击了
9、ScrollView内嵌的滑动条(第三天)
只能一个内容,不如ListView好使,特殊情况需要
10、ListView放置列表的神器(8月14号列表打气筒后面有详细):
android:fastScrollEnabled="true":设置滚动条
java代码中添加元素:lv.setAdapter(new BaseAdapter());
6月15号读写文件及xml解析
this:安卓上下文,可以理解是一个对象
1、读写文件:
(1)写文件:
FileOutputStream outputStream=new FileOutputStream(file);
outputStream.write((usernameString+"##"+passwordString).getBytes());
(2)读文件:
FileInputStream inputStream=new FileInputStream(file);
BufferedReader bf=new BufferedReader(new InputStreamReader(inputStream));
String info = bf.readLine();
2、getCacheDir与getFilesDir的区别
getCacheDir:获取/data/data/包名/cache目录
getFilesDir:获取/data/data/包名/files目录
区别:cache是缓存区(图片等信息可自动销毁),files是数据区(重要的信息用户名密码)
3、sd卡:
Environment.getExternalStorageDirectory():重要,返回sd卡存储目录
(1)地址:/mnt/sdcard(Environment.getExternalStorageDirectory())
(2)数据需要权限:
写:android.permission.WRITE_EXTERNAL_STORAGE
读:android.permission.READ_EXTERNAL_STORAGE
(3)Environment.getExternalStorageDirectory():重要,返回sd卡存储目录
(4)sd卡是否存在,先获取字符串与常量对比
String externalStorageState = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(externalStorageState)){
System.out.println("够用");
}
(5)sd卡是否有可用空间,获取可用容量
long size = Environment.getExternalStorageDirectory().getFreeSpace();
String info = Formatter.formatFileSize(this, size);//转换为可视的
Toast.makeText(this, "可用空间"+info, Toast.LENGTH_SHORT).show();
4、文件权限:
(1)私有的文件:
自己应用文件目录,别的应用无法读取。真实手机没有root权限,看不到data下的文件
(2)共有文件rw(一般不会用,可读可写的文件):
FileOutputStream outputStream = openFileOutput("public.txt", Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
(3)只读r:Context.MODE_WORLD_READABLE
(4)只写w:Context.MODE_WORLD_WRITEABLE
5、SharedPreference保存数据sp:
(1)声明sp:
private SharedPreferences sp;
(2)初始化sp:
sp = this.getSharedPreferences("info", 0);
(3)得到编辑器保存数据:
Editor editor = sp.edit();
editor.putString("username", usernameString);
editor.putString("password", passwordString);
//保存,要不全成功要不全失败
editor.commit();
putInt等不做演示
(4)直接从文件读取数据:
String usernameS = sp.getString("username", "");
String passwordS = sp.getString("password", "");
6、xml文件读取(*与json处理同等重要):
(1)直接用StringBuild组装成xml文件:
会有问题有xml的标签会报错
(2)用xml序列化器:
String fileName="text";
//1、得到xml序列化器
XmlSerializer serializer = Xml.newSerializer();
//2、指定序列化器的一些初始参数
File file = new File(this.getFilesDir(), name+".xml");
os = new FileOutputStream(file);
serializer.setOutput(os, "utf-8");//编码集和输出流
//3、写xml
serializer.startDocument("utf-8", true);//文档的开始
serializer.startTag(null, "student");//开始标签
serializer.startTag(null, "id");
serializer.text("学生编号是");
serializer.endTag(null, "id");
serializer.startTag(null, "name");
serializer.text("学生名称是");//写文本
serializer.endTag(null, "name");
serializer.endTag(null, "student");//结束标签
serializer.endDocument();//文档的结束
(3)XmlPullParser解析xml文件:
文档开始是0
文档结束时1
开始标签2
结束标签3
文本节点是4
//1、获取一个xml解析器
XmlPullParser parser = Xml.newPullParser();
//2、设置解析器的初始化参数
File file = new File(this.getFilesDir(), name+".xml");
FileInputStream inputStream = new FileInputStream(file);
parser.setInput(inputStream, "utf-8");
//3、解析xml文件
int type = parser.getEventType();
while (type!=XmlPullParser.END_DOCUMENT) {//判断是否结束
String tagName = parser.getName();//标签名,text没有名字
if (type==XmlPullParser.START_TAG) {//开始节点
String nextText = parser.nextText();//获取该节点的下一个值(该节点的值)
//还可以加上判断进行处理
}
type=parser.next();//获取下一个节点值
}
6月16号安卓数据库
1、创建数据库:
(1)定义一个数据库帮助类:
MyDataBaseOpenHelper extends SQLiteOpenHelper
(2)加入一个构造方法:
@param context 上下文
@param testdb 数据库文件
@param null 默认游标工厂,从数据库文件的头部开始
@param 1 数据库版本号,最小是1
(3)new帮助类对象:
//数据库不会创建,得到一个对象
MyDataBaseOpenHelper helper = new MyDataBaseOpenHelper(this);
//数据库创建出来
helper.getReadableDatabase();
2、onCreate
数据库创建时调用的方法,只会执行一次,初始化表结构
创建表:db.execSQL("create table student(_id integer primary key autoincrement,name varchar(20),phone varchar(20))");
3、onUpgrade:
当数据库需要更新时调用的方法,数据库版本号更新,只能升级不能降级
参数oldVersion:旧版本
参数newVersion:新版本号
4、ListView(具体例子第三天):
(1)在布局xml文件声明listview控件
(2)在java代码findview ById() 写一个MyAdpter继承BaseAdapter找到,listview控件设置数据适配器,
(3)getCount()确定listview里面有多少个条目
(4)getView(int position) 返回某个位置要显示的view对象
(5)View.inflate() 打气筒 可以把xml文件转成view显示
5、另一种增删改查:
Google组合好的:insert、delete、update、query
6、数据库事务:
要么全成功,要么全失败
例子:银行转账a-100,b+100.突然停电(try)
6月17号访问网络(最重要的操作,权限很重要)
本期示例代码第五天主页登录类
1、访问网络资源(面向过程方式,不方便。3中会面向对象写HttpClient方式):
(1)Android访问网络需要权限:
开启android.permission.INTERNET
(2)不能在主进程中访问:
只能new Thread中run中是真正的方法然后start:new Thread(){ run(){ }}.start();
(3)get请求方式:
//1、得到图片的url路径
URL url = new URL(path);
//2、通过路径获取一个链接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);//设置超时时间
//3、得到服务器的返回信息
String type = conn.getContentType();//返回数据类型
int code = conn.getResponseCode();//返回状态码
InputStream is = conn.getInputStream();//获取流
(4)post请求方式,与get相同不再记录:
//1、设置请求方式:必须大写
conn.setRequestMethod("POST");
//2、设置http请求数据类型为表单类型
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//3、设置给服务器写的数据长度
String data="username="+ usernameString + "&password=" + passwordString;
conn.setRequestProperty("Content-Length", data.length()+"");
//4、记得指定要给服务器写数据
conn.setDoOutput(true);
//5、开始向服务器写数据
conn.getOutputStream().write(data.getBytes());
(5)url请求有中文和特殊字符需要编码:
Android端:URLEncoder.encode(passwordString, "utf-8")
后端也需要处理,与工程编码格式无关。因为拿到url有中文,默认是iso-8859-1的,所以需要转码。不然是????乱码:username = new String(username.getBytes("iso-8859-1"),"utf-8");
后端向前端返回数据只需要Android处理即可,编码一致
2、消息机制处理:
(1)子线程中不能更新图片和打印吐司:
Handler : 消息处理器, 可以发送消息给主线程的消息队列.
Message Queue: 消息队列,主线程里面的一个消息队列.
Looper : 轮询器,检查消息队列里面是否有消息.---> HandleMessage();
(2)更新ui和打印吐司
//1、先在成员位置声明Handler
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
处理逻辑...};
};
//2、利用handler发送消息
Message msg = Message.obtain();
msg.what=SUCCESS;//设置标识
msg.obj=bitmap;//设置值
handler.sendMessage(msg);//发送
//3、接收到消息进行处理:
switch (msg.what) {
case SUCCESS://成功
Bitmap bitmap=(Bitmap) msg.obj;
iv.setImageBitmap(bitmap);
break;
完成图片处理
3、面向HttpClient浏览器对象编写(接口测试也常用,实际开发用4中更方便的方式):
(1)get请求方式:
//1、创建浏览器对象
HttpClient client=new DefaultHttpClient();
//2、根据请求方式把地址加入
HttpGet get=new HttpGet(path);
//3、执行请求,返回响应数据
HttpResponse response = client.execute(get);
//4、解析
int code = response.getStatusLine().getStatusCode();
InputStream is = response.getEntity().getContent();
(2)post请求方式(与get相同不再记录):
HttpPost post=new HttpPost(path);
//1、封装NameValuePair列表
List<NameValuePair> parameters=new ArrayList<NameValuePair>();
//2、向列表中添加参数
parameters.add(new BasicNameValuePair("username", usernameString));
parameters.add(new BasicNameValuePair("password", passwordString));
//3、将列表转换为实体entity
post.setEntity(new UrlEncodedFormEntity(parameters,"utf-8"));
4、采用开源项目提交到服务器(里面有线程池能提高速度):
get与post方式基本一致,只需把方法名换掉即可
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params=new RequestParams();
params.add("username", usernameString);
params.add("password", passwordString);
client.post(path, params , new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
new String(responseBody);
//成功业务逻辑代码
}
@Override
public void onFailure(int statusCode, Header[] headers,
byte[] responseBody, Throwable error) {
//失败业务逻辑代码
}
});
8月14号列表打气筒、多页面、图片显示、加载中展示
好久没学习:详细内容参考第四条demo
1、列表打气筒,大数量时不卡。图片网络直接显示(3)中:
(1)写一个ListView,再写一个item,两个页面写好后可以设计格式
(2)用上面写的ListView调用方法,NewsAdapter()是改类下创建的内部类
lv.setAdapter(new NewsAdapter());
(3)编写NewsAdapter类(NewsAdapter extends BaseAdapter)
实现BaseAdapter的四个方法,最重要的是getCount和getView:
getCount://返回条目个数,所有内容集合的个数
直接改返回值,list.size();
getView:
View view=null;
if (convertView==null) {//没有则创建,有在缓存中读取,用item生成
view=View.inflate(NewPageActivity.this, R.layout.item, null);
}else{
view=convertView;
}
NewsItem newsItem = newsItems.get(position);
//item的控件
TextView tv_item_title = (TextView) view.findViewById(R.id.tv_item_title);
tv_item_title.setText(newsItem.getTitle());
//图片进行展示,该包在第四天中可复制
SmartImageView iv_item=(SmartImageView) view.findViewById(R.id.iv_item);
//通过url获取图片,然后展示出来
iv_item.setImageUrl(newsItem.getImage());
return view;
2、从主页跳转到别的页面(多层页面,记得注册AndroidManifest.xml):
//点击按钮触发操作NewPageActivity是新的界面,新界面要继承Activity
public void clickNewPage(View v) {
Intent intent=new Intent();
intent.setClass(MainActivity.this, NewPageActivity.class);
startActivity(intent);
}
3、图片直接显示:
//从远程获取输入流
InputStream is = conn.getInputStream();
//转化为位图
Bitmap bitmap = BitmapFactory.decodeStream(is);
//展示出来
iv.setImageBitmap(bitmap);
4、加载中友好展示:
(1)先写页面并隐藏,visibility="invisible"表示隐藏,ProgressBar 是转圈内容,TextView显示文本
<LinearLayout
android:visibility="invisible">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载中。。。"/>
</LinearLayout>
(2)点击按钮是先展示控件:
ll_loading.setVisibility(View.VISIBLE);//开启
(3)结束时关闭控件:
ll_loading.setVisibility(View.INVISIBLE);//隐藏进度显示
8月15号文件上传、多线程断点下载
1、文件上传(一定要开启权限):
(1)开启权限(重点)
读权限:android.permission.READ_EXTERNAL_STORAGE
写权限:android.permission.WRITE_EXTERNAL_STORAGE
(2)利用开源的AsyncHttpClient发送post请求
File file=new File(path);
//只需将参数key与需要的参数对应即可,value是文件对象
params.put("upload", file);
2、文件多线程断点下载,玩具代码,实际用框架4中:
下载逻辑:
(1)连接服务器,获取文件大小
(2)本地创建一个空文件
(3)分配线程下载内容
(4)启动多线程下载
多线程断点下载类逻辑:
(1)记录上次下载位置的文件(数据库)判断是否存在,存在则读取后更改开始位置(默认为起始点)
(2)判断开始位置是否大于结束位置,大于则直接结束
(3)请求服务器,下载指定范围的数据c:onn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
指定本地文件写入的开始位置:raf.seek(startIndex);//线程执行的开始位置
(4)将网络输入流转换为byte数组后循环写入文件
(5)写入一次向文件中记录一下(真实用数据库)
(6)所有线程下载结束后删除临时文件,synchronized用来同步线程
java代码(testandroid中的DownloadTest类)
public class DownloadTest {
private static final int threadCount=3;
private static final String path="http://localhost:8080/SpringMVC/views/pycharm.exe";
private static int runningThreadCount;
public static void main(String[] args) throws Exception {
//1、连接服务器,获取文件大小length
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if (code==200) {
int length = conn.getContentLength();
System.out.println(length);
//2、本地先创建一个空文件,存放下载的文件
RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
raf.setLength(length);
raf.close();
//3、分配每个线程的块大小(下载位置),最后一个线程需要下载多一些直接到最后
int blockSize = length/threadCount;
runningThreadCount=threadCount;
for (int threadId = 0; threadId < threadCount; threadId++) {
int startIndex = threadId*blockSize;
int endIndex = (threadId+1)*blockSize-1;
if (threadId==threadCount-1) {
endIndex=length-1;
}
//4、启动线程下载
new DownloadThread(threadId, startIndex, endIndex).start();
}}}
private static class DownloadThread extends Thread{
private int threadId;//线程id
private int startIndex;//开始真实位置
private int endIndex;//结束位置
public DownloadThread(int threadId, int startIndex, int endIndex) {
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
System.out.println(threadId+"号线程下载的范围为:"+startIndex+" ~ "+endIndex);
}
public void run() {
super.run();
try {
//1、记录下载位置的文件,判断是否存在,存在读取后获取上次的位置放到开始位置,不存在从开始下载
File file = new File(threadId+".position");
if (file.exists() && file.length()>0) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
startIndex=Integer.parseInt(new String(bufferedReader.readLine()));
System.out.println(threadId+"接着下载,上次位置:"+startIndex);
bufferedReader.close();
}else {
System.out.println(threadId+"从开始下载");
}
//如果开始位置大于或等于结束位置,不进行下载,小于则下载
if (startIndex < endIndex) {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//2、放入请求网络的位置以及本地文件存放开始的位置
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rw");
raf.seek(startIndex);//线程执行的开始位置
//3、获取网络请求输入流与buffer进行转换
InputStream is = conn.getInputStream();
byte[] buffer=new byte[1024*1024];
int len=-1;
while (-1!=(len=is.read(buffer))) {
//4、向本地文件写数据,并且记录本次写入的位置
raf.write(buffer,0,len);
startIndex+=len;
//5、将写入的位置保存到本地文件中,FileOutputStream会出现没写入的情况,用RandomAccessFile保证每次都能写入,但是耗费硬盘
//System.out.println("线程"+threadId+"----"+new String(buffer)+"下载到的位置:"+startIndex);
RandomAccessFile fos = new RandomAccessFile(file,"rwd");
fos.write((startIndex+"").getBytes());
fos.close();
}
raf.close();
is.close();
}
System.out.println("线程"+threadId+"下载完毕了");
//最后所有线程结束后删除临时文件,synchronized用来同步线程
synchronized (DownloadTest.class) {
runningThreadCount--;
if (runningThreadCount<=0) {
for (int i = 0; i < threadCount; i++) {
File ft=new File(i+".position");
ft.delete();
}}}} catch (Exception e) {
e.printStackTrace();}}}
//获取文件名称
public static String getFileName(String path){
int start=path.lastIndexOf("/")+1;
return path.substring(start);
}}
3、Android下载进度条:
(1)写界面ui,ProgressBar:
<ProgressBar
android:id="@+id/pb0"
android:layout_below="@id/download"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
(2)获取:
(3)指定位置
int max = endIndex-index;//总大小
int progress = startIndex-index;//当前位置
if (threadId==0) {
pb0.setMax(max);
pb0.setProgress(progress);
}
4、Android开源框架下载(重要常用)
(1)导包:第五天中xUtils-2.6.14.jar
(2)HttpUtils实例化一个对象
HttpUtils http=new HttpUtils();
(3)直接调用下载方法:
//1、下载地址,下载文件存放路径,是否断点续传,RequestCallBack类
http.download(path, Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+getFileName(path),true, new RequestCallBack<File>() {
@Override
//2、成功做的操作
public void onSuccess(ResponseInfo<File> arg0) {
Toast.makeText(UploadFileActivity.this, "下载成功",Toast.LENGTH_SHORT).show();
}
//3、进度条
@Override
public void onLoading(long total, long current, boolean isUploading) {
super.onLoading(total, current, isUploading);
pb0.setMax((int) total);//total总长度
pb0.setProgress((int) current);//current当前进度
}
@Override
public void onFailure(HttpException arg0, String arg1) {
Toast.makeText(UploadFileActivity.this, "网络连接失败"+arg1,Toast.LENGTH_SHORT).show();
}
});
附录:断点续传图片
作者:科研小田 https://www.bilibili.com/read/cv3350212 出处:bilibili