Android Dev Bugs

什么是智者?就是一个坑不跌两回呗

The wiser man doesn’t fall into the same pit twice.

基础不牢、地动山摇

Without a solid foundation, the earth will shake.

Java参数传递-引用传递vs.值传递

Java中的变量类型基本分为两种:基本类型和引用类型。

基本类型为全小写字母,如:int, long, short, char等;
引用类型为首字母大,如:String, Integer, User 等。
其中引用类型中又有一些是“不可变引用类型”,如:String, Integer等。
对于基本类型作为方法的参数传递的是值本身,没什么问题。
对于引用类型作为方法的参数传递的是地址。

理解了参数传递的本质
首先,基本类型的参数,传递的肯定是值本身,因为基本类型的变量存在JVM的栈内存中。不存在堆内存地址的概念;

其次,引用类型的参数(不管是可变引用类型还是不可变引用类型)传递的都是该变量所指向的堆内存的地址。而在调用方法的时候,会将这个地址的值赋给方法的局部变量,使得这个局部变量也指向相应的堆内存。

只不过,如果是不可变引用类型的参数,当对局部变量赋新值时,本质上是开辟了新的内存区域放入新值,使局部变量指向新的内存区域,因此不会改变调用端变量的值。

而如果是可变引用类型的参数,当改变对象的内容时,改变是这个对象所在内存中的值,因此,在调用端读取的时候是改变后的值。

How to create a release signed apk file using Gradle?

Put this into ~/.gradle/gradle.properties

1
2
3
4
RELEASE_STORE_FILE={path to your keystore}
RELEASE_STORE_PASSWORD=*****
RELEASE_KEY_ALIAS=*****
RELEASE_KEY_PASSWORD=*****

Modify your build.gradle like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
signingConfigs {
release {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
....

Android Studio : unmappable character for encoding UTF-8

Add system variable (for Windows) “JAVA_TOOL_OPTIONS” = “-Dfile.encoding=UTF8”.

Gradle的文件编码设置

有时,用命令行编译时,对于UTF8文件中的中文,会出现乱码的情况,如

1
2
F:\workspace\TestHello\src\main\Java\com\win16\testhello\ShortLifeObject.java:8: error: unmappable character for encoding GBK
//鐪熸鐨勫崟渚嬶紝鎴戜滑瑕佺‘淇濊繖涓璞″彧鑳芥湁涓?浠?

这个时候需要修改gradle.bat中的JAVA虚拟机变量DEFAULT_JVM_OPTS,默认情况这个变量是空,需要改为:

set DEFAULT_JVM_OPTS=”-Dfile.encoding=UTF-8”

重新编译即可。

对于使用intellij idea或是androidstudio的,可修改配置文件vmoption,在文件尾部增加一行

-Dfile.encoding=UTF-8

即可支持utf8中文

Android Studio:Warning when generate Signed Apk in release mode Warning:com.fasterxml.jackson.databind

ignore those warning in your proguard file using:

1
2
-keepnames class com.fasterxml.jackson.databind.** { *; }
-dontwarn com.fasterxml.jackson.databind.**

Error: Gradle: execution failed for task ‘:app:preDexDebug’

We’ve seen this problem in the past when our project was compiling with a version of Java different from the one used to compile the library. The magic number is just used to identify class files so that is not the problem here. The issue is the java version (0034.0000 == Java 8).

The easiest thing to do is target Java 6, which may require removing newer syntax from your code. In our case, both the project and library were ours so we were able to add the following to force the version of Java that we needed:

Android Libraries

for android libraries, add this code to the “android” extension object:

1
2
3
4
5
6
7
8
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
}
...
}

Java Libraries

for java libraries, add this code at the “top level”:

1
2
3
4
5
6
7
apply plugin: 'java'
version '1.8.1'
group 'com.yourcompany.package'
sourceCompatibility = JavaVersion.VERSION_1_6 //these two lines
targetCompatibility = JavaVersion.VERSION_1_6 //are the only ones that matter

NOTE: the last two lines are the only ones that matter, I added the others just to show where those lines belong, in respect to the rest of your gradle build file.

Android Studio 错误 com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

第1步
添加依赖于你的build.gradle支持MultiDex库

dependencies { … compile ‘com.android.support:multidex:1.0.1’ … }

第2步
在buildType或productFlavor中开启multiDexEnabled。

defaultConfig { … multiDexEnabled true … }

Error:Execution failed for task ‘:app:transformClassesWithDexForDebug’ in android studio Ask Question

android framework 用来快速开发的android框架

android_framework
an android framework in order for rapid development

1.开发环境

环境为android studio + jdk1.7

2.框架结构

该框架分为三个部分:

libcore

libcore-ui

testsample

第三层为测试代码,重点在第一和第二层…

3.框架详细概述

第一层libcore

该层为基础核心代码层,该层的代码特点是封装了应用所应该使用的基础功能,好处是封装的功能仅仅提供简单的接口,使得应用只需要更改libcore的封装实现,而不用修改底层的代码,从而轻松实现功能的变更,功能列表如下所示


  1. Application封装,使用了weakRefrence指向当前Activity的context,方便使用,还增加了应用crash,应用关闭等处理

  2. 最基础的Activity和Fragment类,配合Application类和ActivityManager类进行Activity的集中管理

  3. ActivityManager类,使用栈来管理所有的activity

  4. BaseNetApi类,实现了网络请求,网络访问的底层使用的是volley框架。现在提供两种方案:第一种就是可更换的网络框架,为了可更换,就要对volley进行大程度的封装,所有子module不可直接使用volley相关类,以后网络框架更改,只需要修改这几个相关类即可,由于volley功能的复杂性,只能封装最基本的网络访问功能,tag和cache等功能由于不通用性,暂时不封装;

  5. BaseVolleyApi类,第二种就是纯粹的volley框架,不会更换网络访问框架,只需对其进行最基本的封装,所有功能类都可在子module中使用,所以会增大项目对volley框架的耦合性

  6. ImageLoader类,用来进行图片的加载,封装的是volley的imageloader功能,支持lrucache和sd卡二级存储功能

  7. log类,用来打印log,打印的日志信息非常完整

  8. Toast类,该类用来弹出toast,支持弹出toast的位置

  9. GuideManager类,用来显示指引蒙版,支持全屏展示和只在内容区域展示

  10. BaseDialog类,定义了一个应用dialog所应该具备的基础行为

  11. 数据库相关类,将数据库类进行了非常便捷的封装,创建数据库应该继承自BaseDB类,为了该数据库的访问应该再创建一个helper类继承自BaseDBHelper,封装该数据库的所有操作,另外还需要对表名和列名进行了枚举的封装,这样使用该数据库直接使用该枚举类获取表名和表的相关列名。对数据库的版本升级也做了相应快捷的处理

  12. CacheManager类,这个类使用SharedPreference来存储基本对象,有临时和永久两种,临时存储将会在每次应用退出之后自动清空,永久存储则永久存储

  13. FileDownloadManager类,用来下载相关文件,为多线程断点续传式下载,支持开始,停止和删除操作

  14. Utils类:

    • CommonUtils,用来集中管理一些杂项函数,比如dp2px等

    • FileUtils,用来管理文件的相关操作

    • ImageUtils,用来处理图片的相关操作



第二层libcore-ui层

该层为基础核心扩展层,扩展libcore的层的代码,并且定义应用的基本样式,够统一样式,方便管理


  1. 扩展实现的Activity和Fragment类,BaseActivity类中定义了整个应用的基本简单样式(现在提供两种样式,顶部透明样式和底部透明样式),顶部bar的样式(顶部bar有自定义bar和系统控件toolbar)等,BaseActivityWithPopWindow类继承BaseActivity类,实现了底部的弹出框;Fragment类定义了fragment和activity之间的通信方式和topbar的交互,

  2. NetApi类,NetApi继承自BaseNetApi类,在原来的基础上扩展相关的功能,支持自定义继承自volley request的请求,额外的处理就只是在NetApi类中添加相应的函数

  3. VolleyApi类,用来对BaseVolleyApi类进行功能扩展

  4. PermanentCacheDB类,用来存储一些和应用生命周期相关的变量,写入数据库,永久保存

  5. WebFragment类,该fragment用来显示网页,可以单独作为一个fragment嵌入一个页面的任何地方

  6. WebActivity类,该activity用来展示网页,传入url即可显示网页,有进度条和刷新操作

  7. AppDialog类,该类继承自父类BaseDialog类,定义了基本的样式,实现了基础的行为

  8. DialogCreator类,该类用来生成基本样式的dialog

  9. LoadingDialog类,用来定义一个应用最基本的加载框

  10. 基本实用的控件:

    • SimpleGridLayout类,自定义网格布局,自动换行,自定义attr

    • FlowLayout类,自定义流式布局,支持方向选择,自动换行,自定义attr



第三层应用层

该层为模拟应用层,用来测试下层的代码。一个应用在使用了libcore层和libcore-ui层之后,可能还需要在封装一层或几层module,但是保证最基础的两层是应用所通用的module即可

android 特殊用户通知用法汇总–Notification源码分析

notification
android-custom-notification-tutorial

编译时替换资源 - Android重叠包与资源合并一见

处理多个资源文件夹

每个sourceSet可以定义多个资源文件夹,举个例子:

1
2
3
android.sourceSets {
main.res.srcDirs = ['src/main/res', 'src/main/res2']
}

1
2
3
4
5
6
7
8
9
10
11
12
13
android {
...
aaptOptions {
additionalParameters '-S',
'/Users/yifan/dev/github/Testapp/app/src/main/res3',
'-S',
'/Users/yifan/dev/github/Testapp/app/src/main/res2',
'--auto-add-overlay'
noCompress 'foo', 'bar'
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
}
...
}

这种情况下,两个资源文件夹具有相同优先级,即如果一个资源在两个文件夹都声明了,合并会报错。

分类整理res/Layouts中的布局文件(创建子目录)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sourceSets {
main {
res.srcDirs =
[
'src/main/res/layouts/mainpage',
'src/main/res/layouts/investment',
'src/main/res/layouts/productlist',
'src/main/res/layouts/myaccount',
'src/main/res/layouts/setting',
'src/main/res/layouts',
'src/main/res'
]
}
}

java中用正则表达式解析LRC文件

正则表达式应用之提炼百度歌词的实现代码

时间段很有规律,一般以“[”开头以“]”结尾,有重复的时候就会出现两段时间段。第一时间想到了正则表达式,于是就用正则表达式写了如下的程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8" />
<meta name="author" content="" />
<meta name="keywords" content="" />
<meta name="description" content="" />
</head>
<body>
<?php
$contents2 = "";
$filename = "html/tingshuo.lrc";
$contents = file_get_contents($filename);
echo nl2br($contents);
echo "<br /><br />";
preg_match_all("/\][^\[].*+/",$contents,$array);
$numArray = count($array[0]);
for($i = 0;$i<$numArray;$i++){
$contents2.=trim($array[0][$i],"\]");//去除左边的“]”
$contents2.="<br />";
}
echo "<br /><h2>这是处理后的歌词记录</h2><br />";
echo $contents2;
echo "<br /><h2>这是未处理的歌词记录</h2><br />";
echo "<br />";
echo "<pre>";
print_r($array);
echo "</pre>";
?>
</body>
</html>

Java 里把 InputStream 转换成 String 的几种方法

  1. 使用 JDK 5 的 Scanner
  2. JDK1.4 及之前的 BufferedReader 法
  3. JDK1.4 及之前的 readBytes 法
  4. Apache commons IOUtils.toString 法
  5. Google guava 的 CharStreams 方法
  6. JDK 7 的 NIO readAllBytes

Android 指定销毁一个Activity

static MessagePushActivity instance;
instance=this;//在onCreate里面写
instance = null;//在onDestroy里面写
MessagePushActivity.instance.finish();//在其它的activity里面使用

在android程序中使用配置文件properties

在Android中,比起用纯字符串读写并自行解析,或是用xml来保存配置,
Properties显得更简单和直观,因为自行解析需要大量代码,而xml的操作又远不及Properties方便

android读取工程根目录下文件内容

安卓某些资源目录,RAW目录以及ASSETS目录下的文件都能轻易读取,但是工程根目录下的文件Android确没有提供方法读取,只能自己想办法,曲线救国了android应用的后缀名称为.apk其实就是一个压缩文件,可以用解压缩工具查看里面的文件信息,那我想也可以通过读取压缩包文件的方式读取工程根目录下的文件的内容,android也提供了读取压缩文件信息的接口。那么就需要找到这个压缩包的存在,还好android提供了一个方法可以读取到apk的信息context.getPackageCodePath(),下面是详细代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private static File findFile(Context context) {
String str3 = context.getPackageCodePath();
try {
ZipInputStream zipInput=new ZipInputStream(new FileInputStream(str3));
ZipEntry currentZipEntry = null;
while ((currentZipEntry=zipInput.getNextEntry())!=null) {
String name = currentZipEntry.getName();
if (!currentZipEntry.isDirectory()) {
Log.d("zengnengxin", name + "is a normal file");
if( name.equalsIgnoreCase("AndroidManifest.xml")){
File file = new File(context.getFilesDir() + File.separator + name);
file.createNewFile();
// get the output stream of the file
FileOutputStream out = new FileOutputStream(file);
int ch;
byte[] buffer = new byte[1024];
//read (ch) bytes into buffer
while ((ch = zipInput.read(buffer)) != -1){
// write (ch) byte from buffer at the position 0
out.write(buffer, 0, ch);
out.flush();
}
out.close();
return file;
}
}
}
zipInput.close();
} catch (Exception e) {
// TODO: handle exception
}
return null;
}

Android开发中获取assets文件夹下Xml文件的问题。

assets文件里面的文件在工程被运行的时候是不会被编译的。

直接使用XmlPullParser

我们查看XmlResourceParser源码的时候,就会发现XmlResourceParser实现了两个接口,AttributeSet和XmlPullParser,而实际上XmlPullParser就是帮助我们去读xml文件的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
InputStream in = DBHelper.getDBHelper().getContext().getResources()
.getAssets().open("province.xml");
InputStream is = IOHelper.fromInputStreamToInputStreamInCharset(in,"utf-8");
public void test(InputStream in) {
XmlPullParserFactory factory;
try {
factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(in, "UTF-8");
int evtType = xpp.getEventType();
// 一直循环,直到文档结束
while (evtType != XmlPullParser.END_DOCUMENT) {
switch (evtType) {
case XmlPullParser.START_TAG:
String tag = xpp.getName();
System.out.println(tag);
break;
case XmlPullParser.END_TAG:
break;
default:
break;
}
//获得下一个节点的信息
evtType = xpp.next();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

assets文件夹资源的访问

assets文件夹里面的文件都是保持原始的文件格式,需要用AssetManager以字节流的形式读取文件。

  1. 先在Activity里面调用getAssets() 来获取AssetManager引用。
  2. 再用AssetManager的open(String fileName, int accessMode) 方法则指定读取的文件以及访问模式就能得到输入流InputStream。
  3. 然后就是用已经open file 的inputStream读取文件,读取完成后记得inputStream.close() 。
    4.调用AssetManager.close() 关闭AssetManager。
    需要注意的是,来自Resources和Assets 中的文件只可以读取而不能进行写的操作

Android获取assets文件夹中的数据并写入SD卡示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*将assets文件夹下的数据库写入SD卡中
* @author Dave */
public class WriteToSD {
private Context context;
String filePath = android.os.Environment.getExternalStorageDirectory()+"/weather";
public WriteToSD(Context context){
this.context = context;
if(!isExist()){
write();
}
}
private void write(){
InputStream inputStream;
try {
inputStream = context.getResources().getAssets().open("addressId.db");
File file = new File(filePath);
if(!file.exists()){
file.mkdirs();
}
FileOutputStream fileOutputStream = new FileOutputStream(filePath + "/database.db");
byte[] buffer = new byte[512];
int count = 0;
while((count = inputStream.read(buffer)) > 0){
fileOutputStream.write(buffer, 0 ,count);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
System.out.println("success");
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean isExist(){
File file = new File(filePath + "/database.db");
if(file.exists()){
return true;
}else{
return false;
}
}
}

android如何打印当前的线程及进程

常用语句:
Android.os.Process
//获取当前进程的方法
android.os.Process.getElapsedCpuTime():获取消耗的时间。
android.os.Process.myPid():获取该进程的ID。
android.os.Process.myTid():获取该线程的ID。
android.os.Process.myUid():获取该进程的用户ID。
android.os.Process.supportsProcesses:判断该进程是否支持多进程。

// 获取/设置线程优先级
getThreadPriority(int tid):获取指定ID的线程的优先级。
setThreadPriority(int priority):设置当前线程的优先级。
setThreadPriority(int tid,int priority):设置指定ID的线程的优先级。

//管理进程
killProcess(int pid):杀死指定的进程。
sendSignal(int pid,int singal):向指定的进程发送信号。

android.os.Environment
//获取系统环境变量
getDataDirectory():获取当前系统中数据文件夹环境变量。
getDownloadCacheDirectory():获取当前系统中下载缓存文件环境变量。
getExternalStorageDirectory():获取当前系统中外部存储文件环境变量。
getRootDirectory():获取当前系统中根文件环境变量。

Android setTag和getTag()的使用

Tag不像ID是用标示view的。Tag从本质上来讲是就是相关联的view的额外的信息。它们经常用来存储一些view的数据,这样做非常方便而不用存入另外的单独结构。
convertView中的TAG

  1. 对于使用了LayoutInflater对象进行View扩充的Tag的使用
    在之前,在adapter中,我们在getView中是这么些的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder =null;
    if (convertView ==null) {
    holder =new ViewHolder();
    convertView =inflater.inflate(R.layout.vlist2,null);
    holder.img = (ImageView) convertView.findViewById(R.id.img);
    holder.title = (TextView) convertView.findViewById(R.id.title);
    holder.info = (TextView)
    convertView.findViewById(R.id.info);
    // setTag的妙用
    convertView.setTag(holder);
    }else {
    // setTag的妙用
    holder = (ViewHolder) convertView.getTag();
    }
    ……略
    }

    注意标红的地方,他们是使用了Tag的。
    首先我们要知道setTag方法是干什么的,他是给View对象的一个标签,标签可以是任何内容,我们这里把他设置成了一个对象,因为我们是把vlist2.xml的元素抽象出来成为一个类ViewHolder,用了setTag,这个标签就是ViewHolder实例化后对象的一个属性。我们之后对于ViewHolder实例化的对象holder的操作,都会因为Java的引用机制而一直存活并改变convertView的内容,而不是每次都是去new一个。我们就这样达到的重用——我希望我说清楚了。如果有更简单的解释,请指教。
    这是我们在Adapter中的使用,那么我们在这里不使用Tag标签会怎么样呢?
    我们试想,如果我们不用Tag标签,那么我们的对象如何与convertView缓存结合并达到合理的效率利用?貌似答案并不明朗——所以使用Tag是比较明智的做法。

  2. 对于没有使用LayoutInflater对象进行View扩充的Tag的使用。

    1
    2
    3
    4
    5
    6
    7
    if (convertView != null) {
    view = convertView;
    ...
    } else {
    view = new Xxx(...);
    ...
    }

    这是我们的程序,我们看到,貌似没有用Tag——是的,当没有使用LayoutInflater进行View的扩充的时候,是没有必要用的,虽然也可以用。

  3. 对于其他View的Tag使用
    我们可以对所有的View对象进行操作,至于怎么用,就看作者怎么想的了,下面举例说一个View的子类button对于tag的一个使用。
    直接贴代码了:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    publicclass ButtonTagTestActivityextends Activityimplements OnClickListener {
    /** Called when the activity is first created. */
    @Override
    publicvoid onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button button1 = (Button) findViewById(R.id.button1);
    Button button2 = (Button) findViewById(R.id.button2);
    Button button3 = (Button) findViewById(R.id.button3);
    button1.setTag(1);
    button2.setTag(2);
    button3.setTag(3);
    button1.setOnClickListener(this);
    }
    @Override
    publicvoid onClick(View arg0) {
    // TODO Auto-generated method stub
    int tag = (Integer) arg0.getTag();
    switch (tag) {
    case 1: {
    Toast.makeText(this,"我是button1", Toast.LENGTH_LONG).show();
    break;
    }
    case 2: {
    Toast.makeText(this,"我是button2", Toast.LENGTH_LONG).show();
    break;
    }
    case 3: {
    Toast.makeText(this,"我是button3", Toast.LENGTH_LONG).show();
    break;
    }
    default: {
    break;
    }
    }
    }
    }

    Xml页面代码就不贴了。这个例子是点击界面上的3个button然后会显示用户点击的按钮。我们的程序是实现了页面全局监听,在监听前设置了每个button的tag,之后我们在switch的时候,使用getTag取出的标签来看是什么操作。
    这样做的好处是可以将监听集中管理,提高代码的易读性——当然,这是我的自我理解。

看了这么多的实例,我想已经明白了Tag以及convertView。

对我们知道了Tag的作用就是设置标签,标签可以是任意玩意。
以及convertView是如何在程序中使代码运行变的效率的:利用缓存convertView尽可能少实例化同样结构体的对象;

源码地址:http://download.csdn.net/detail/dadaxiaoxiaode/5844903

充分挖掘AndroidMonitor的功能

AndroidStudio 显示不出logcat日志

AndroidMonitor,若logcat 的Restart还不行,就重启IDE
较早前不稳定的bug解决android logcat不打印信息
Android学习笔记——log无法输出的解决方法和命令行查看log日志

java中File类的getPath(),getAbsolutePath(),getCanonicalPath()区别

getPath():

返回的是定义时的路径,可能是相对路径,也可能是绝对路径,这个取决于定义时用的是相对路径还是绝对路径。如果定义时用的是绝对路径,那么使用getPath()返回的结果跟用getAbsolutePath()返回的结果一样

getAbsolutePath():

返回的是定义时的路径对应的相对路径,但不会处理“.”和“..”的情况

getCanonicalPath():

返回的是规范化的绝对路径,相当于将getAbsolutePath()中的“.”和“..”解析成对应的正确的路径
举例如下:

1
2
3
4
File file = new File(".\\test.txt");
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());

返回的结果为:

1
2
3
.\test.txt
E:\workspace\Test\.\test.txt
E:\workspace\Test\test.txt

“..”的情况类似

Android如何检测网络的类型为3G、2G、wap、wifi

Android判断用户的网络类型(2/3/4G、wifi)
android 开发中判断网络是否连接的代码

android 设置textView水平居中显示

  1. 让textView里面的内容水平居中 : android:gravity=”center_horizontal”

    1. 让textView控件在它的父布局里水平居中 android:layout_gravity=”center_horizontal”

    Java 编程下正则表达式判断字符串是否包含中文

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static boolean isContainChinese(String str) {
    Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
    Matcher m = p.matcher(str);
    if (m.find()) {
    return true;
    }
    return false;
    }

    Android里面多行字符串怎么一行行读取?

    1
    2
    3
    4
    String[] lines = 内容.split("\n");
    for(String line : lines) {
    //line就是每一行
    }

    Java list对象列表排序 实例

    1
    2
    3
    4
    5
    6
    7
    Collections.sort(list, new Comparator() {
    public int compare(Object a, Object b) {
    int one = ((Bean) a).getPriority();
    int two = ((Bean) b).getPriority();
    return one - two;
    }
    });

    JAVA编程有一个小数,如何去掉小数部分?

    向上取整:Math.ceil() //只要有小数都+1
    向下取整:Math.floor() //不取小数
    四舍五入:Math.round() //四舍五入

    Android 最简单的SD卡文件遍历程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //检测SD卡是否存在
    if (Environment.getExternalStorageState().equals(
    Environment.MEDIA_MOUNTED)) {
    path = Environment.getExternalStorageDirectory();
    }else{
    Toast.makeText(this, "没有SD卡", Toast.LENGTH_LONG).show();
    finish();
    }
    // 遍历接收一个文件路径,然后把文件子目录中的所有文件遍历并输出来
    private void getAllFiles(File root){
    File files[] = root.listFiles();
    if(files != null){
    for (File f : files){
    if(f.isDirectory()){
    getAllFiles(f);
    }else{
    System.out.println(f);
    }
    }
    }
    }

android 程序中代码如何判断模拟器和真机

一般真机的imei码是唯一的所以可以采用这种方法!

1
2
3
4
5
6
7
8
9
10
11
12
/** 判断是否模拟器。如果返回TRUE,则当前是模拟器
* @param context
* @return
*/
public static boolean isEmulator(Context context){
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId();
if (imei == null || imei.equals("000000000000000")){
return true;
}
return false;
}

提醒:记得要申请READ_PHONE_STATE权限哦

android中arraylist插入数据到第一个位置

1
2
ArrayList m = new ArrayList();
m.add(0, Integer.valueOf(1));

add方法可以指定位置

android设置Activity背景色为透明的3种方法

方法一:这种方法比较简单,只有一个步骤,只需要在配置文件中把需要设置为透明的activity的样式设置为

1
Android:theme="@android:style/Theme.Translucent"

即可,这种方式只改变背景的颜色,对其他控件没有影响。但是它只能把背景设置为完全透明。如果要设置为半透明或者要设置透明的程度无法实现。

方法二:这种方法也比较简单,只需要在方法一的基础上,再布局文件中配置背景颜色就可以

1
android:background="#01000000"

“ #01000000”中“01”表示的是背景透明的程度,这个值只能设置01及以上的值,不能设置为00,及不能设置为完全透明,不过设置为01其实和透明的效果也很接近了,肉眼几乎看不出来区别了。这种方法同样对其他控件没有影响。

方法三:这种方法稍微复杂些,有几个步骤,这种方法对其他控件的透明度也会产生影响,并且可以自己设置透明的程度,相对来说要灵活一些。
第一步,在res/values下建立colors.xml文件,设置一个背景颜色,在这里可以设置你背景的颜色和透明度。
添加上自定义的颜色

1
<color name="transparent">#55ff</color>

第二步,在res/values/下建styles.xml,设置程序的风格

1
2
3
4
5
<style name="Transparent">
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@+android:style/Animation.Translucent</item>
</style>

第三步,把这个styles.xml用在相应的Activity上。即在AndroidManifest.xml中的任意标签中添加

1
android:theme="@style/Transparent"

如果想设置所有的activity都使用这个风格,可以把这句标签语句添加在中。
这个方法不仅对背景透明有效,而且对其他控件也有效,如果其他控件没有设置背景颜色,会呈现出透明的效果。这种方法比较复杂些,如果不是需要对整个页面及控件都有透明度要求,建议使用前面2中方法。

Android图片加载框架最全解析(一),Glide的基本用法

with()方法可以接收Context、Activity或者Fragment类型的参数。也就是说我们选择的范围非常广,不管是在Activity还是Fragment中调用with()方法,都可以直接传this。那如果调用的地方既不在Activity中也不在Fragment中呢?也没关系,我们可以获取当前应用程序的ApplicationContext,传入到with()方法当中。注意with()方法中传入的实例会决定Glide加载图片的生命周期,如果传入的是Activity或者Fragment的实例,那么当这个Activity或Fragment被销毁的时候,图片加载也会停止。如果传入的是ApplicationContext,那么只有当应用程序被杀掉的时候,图片加载才会停止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Glide.with(this).load(url).into(imageView);
String url = "http://cn.bing.com/az/hprichbg/rb/Dongdaemun_ZH-CN10736487148_1920x1080.jpg";
Glide.with(this).load(url).into(imageView);
// 加载本地图片
File file = new File(getExternalCacheDir() + "/image.jpg");
Glide.with(this).load(file).into(imageView);
// 加载应用资源
int resource = R.drawable.image;
Glide.with(this).load(resource).into(imageView);
// 加载二进制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView);
// 加载Uri对象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);
// 占位图就是指在图片的加载过程中,我们先显示一张临时的图片,等图片加载出来了再替换成要加载的图片。
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.into(imageView);
// 因为Glide有非常强大的缓存机制,我们刚才加载那张必应美图的时候Glide自动就已经将它缓存下来了,下次加载的时候将会直接从缓存中读取,不会再去网络下载了,因而加载的速度非常快,所以占位图可能根本来不及显示。
// 串接了一个diskCacheStrategy()方法,并传入DiskCacheStrategy.NONE参数,这样就可以禁用掉Glide的缓存功能。
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
// 异常占位图就是指,如果因为某些异常情况导致图片加载失败,比如说手机网络信号不好,这个时候就显示这张异常占位图。
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
不管我们传入的是一张普通图片,还是一张GIF图片,Glide都会自动进行判断,并且可以正确地把它解析并展示出来。
// load()方法的后面加入了一个asBitmap()方法,这个方法的意思就是说这里只允许加载静态图片,不需要Glide去帮我们自动进行图片格式的判断了。
Glide.with(this)
.load(url)
.asBitmap()
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
// 既然我们能强制指定加载静态图片,就也能强制指定加载动态图片。用了asGif()方法替代了asBitmap()方法
Glide.with(this)
.load(url)
.asGif()
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
//使用Glide在绝大多数情况下我们都是不需要指定图片大小的。
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.override(100, 100)
.into(imageView);

什么叫内存浪费呢?比如说一张图片的尺寸是10001000像素,但是我们界面上的ImageView可能只有200200像素,这个时候如果你不对图片进行任何压缩就直接读取到内存中,这就属于内存浪费了,因为程序中根本就用不到这么高像素的图片。Glide从来都不会直接将图片的完整尺寸全部加载到内存中,而是用多少加载多少。Glide会自动判断ImageView的大小,然后只将这么大的图片像素加载到内存当中,帮助我们节省内存开支。内部的实现原理其实就是 Android高效加载大图、多图解决方案,有效避免程序OOM当中介绍的技术

video-player-android

How to integrate with your project

Add library to project dependencies.

1
2
3
4
5
6
7
8
9
10
11
12
13
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
dependencies {
// snapshot version
compile 'com.github.appunite:video-player-android:master-SNAPSHOT'
// or use specific version
compile 'com.github.appunite:video-player-android:1.0.1'
}

Start video

1
2
3
startActivity(PlayerActivity.getVideoPlayerIntent(context,
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8",
"Video title"));

Android项目实战(三十):Fresco加载gif图片并播放

android-gif-drawable Views and Drawable for displaying animated GIFs on Android

Glide An image loading and caching library for Android focused on smooth scrolling

Glide加载gif动图,Glide带加载动画(动画可以自定义)比imageloader更好用的安卓图片加载库


Android App中使用Glide加载图片的教程




从源码分析Android的Glide库的图片加载流程及特点

如何使视频在VideoView中居中显示

默认情况下,如果视频分辨率小于设备的屏幕分辨率,VideoView在播放视频时都是在左上角显示的,影响美观。如何让居中显示呢?
下面给出解决方法:
1、修改VideoView组件的Layout Parameters的Gravity属性

2、使用“格式工厂”视频处理软件修改视频分辨率,使其等于或大于设备的屏幕分辨率。

Android 设置TextView滑动滚动条和滑动效果

Android TextView属性大全

1、单独的TextView控件设置滚动条

1
2
3
4
5
6
7
<TextView
Android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="file content is empty!"
android:scrollbars="vertical"
android:fadeScrollbars="false"/>

在activity中为这个TextView设置:

1
2
mFileContentView = (TextView) findViewById(R.id.content);
mFileContentView.setMovementMethod(ScrollingMovementMethod.getInstance());

经过上面两个步骤,TextView就可以上下滚动了,如果想自定义滚动条,接着在xml里面加入属性:

1
2
android:scrollbarThumbVertical="@drawable/ic_launcher" //滑块的图片
android:scrollbarTrackVertical="@drawable/ic_launcher" //滑道的图片

ScrollBar由两部分组成,一个是Track(滑道),一个是Thumb(滑块)

2、也可以用ScrollView

1
2
3
4
5
6
7
8
9
10
11
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fadingEdge="vertical">
<TextView
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="file content is empty!"/>
</ScrollView>

删除联系人

Android开发系列(十一):对手机通讯录的读取、添加、删除、查找
android通讯录开发及优化

打开AS,点击工具栏的Analyze-Run Inspection by Name-输入unused resources-选择要搜索的范围回车-查看搜索结果并删除无用的资源文件

android:parentActivityName

android:parentActivityName的作用,就是为了左上角给子Activity加一个返回按钮,具体信息如下:

Android 4.1提高性能、增强用户体验
App 栈导航:通过设置android:parentActivityName改变回退栈的内容,如果栈中没有parentActivity,则合成栈,通过onPrepareNavigateUpTaskStack()改变parentActivity中的内容。

解析网络数据

jsoup Cookbook(中文版)
Download jsoup

Android图片缩放,压缩总结(inSampleSize,Matrix比较)

Android中经常会遇到需要对图片进行缩放及压缩的操作,下面列出3种图片缩放方法:

一.图片缩放

1.inSampleSize(采样率)

优点:效率较高,解析速度快

缺点:采样率inSampleSize的取值只能是2的次方数(例如:inSampleSize=15,实际取值为8;inSampleSize=17,实际取值为16;实际取值会往2的次方结算),因此该方法不能精确的指定图片的大小

2.Matrix

优点:可以精确地指定图片的缩放大小

缺点:是在原bitmap的基础之上生成的,占内存,效率低.

3.ThumbnailUtils

2.2新加的类,实际上是将上述两种方法进行结合并做了封装.

二.图片压缩

往往图片压缩是为了节省网络流量,进行网络传输,一般需要将图片压缩成byte[] 数组.

1
2
3
4
5
public static byte[] BitmapToByte(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 80, baos);//其中80参数表示要压缩的比例
return baos.toByteArray();
}

Android

UI

自己先构想好,树形结构,嵌套/复用,图形化工具验证辅助
知其然,知其所以然

This fact is true that Hello World program is the first program that a programmer writes when he/she start learning a new programming language. Today I thought that I should share the hello world program in different languages. A video is also added for easy understanding of the programs. Let’s take a look on these programs.

Android Studio 之 JNI 开发详解

使用Android Studio 进行NDK开发和调试
Jni接口-深入研究参数的传递
在app level的build.gradle中添加com.android.tools.build:gradle-experimental依赖。
在./app/build.gradle中添加gradle-experimental依赖

dependencies {
    compile 'com.android.tools.build:gradle-experimental:0.7.0'
}

再次在testJni()方法上按快捷键Alt + Enter并回车

#include <jni.h>

JNIEXPORT jstring JNICALL
Java_com_connorlin_jnitest_MainActivity_testJni(JNIEnv *env, jobject instance) {
    // TODO
    return (*env)->NewStringUTF(env, "returnValue");
}

你会发现成功自动生成JNI方法了。

副作用

这种方式有个副作用是 Run app 时可能会报错

此时,只要将gradle-experimental依赖注释掉即可正常运行,同时会保持自动生成代码的功能,直到关闭工程。
这样我们在需要自动生成代码的时候,将gradle-experimental依赖再次打开即可。

什么是NDK?
NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或LINUX系统环境),并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

为什么使用NDK?
1.)代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
2.)可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
3.)提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
4.)便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

什么是JNI?
JNI全称为:Java Native Interface。JNI 是本地编程接口,它使得在 Java 虚拟机内部运行的 Java 代码能够与用其它语言(如 C、C++)编写的代码进行交互。

为什么使用JNI?
JNI的目的是使java方法能够调用c实现的一些函数。

安卓中的so文件是什么?
Android中用到的so文件是一个c++的函数库。在android的JNI中,要先将相应的C语言打包成so库,然后导入到lib文件夹中供java调用。

编译运行前,别忘了把打开了\app\build\intermediates\classes\debug\的Terminal命令行工具关掉,否则占用这个文件夹会导致编译不成功。因为编译的时候,会把build里的东西全部删除再重新生成,如果占用的话,删除不了就会出错。

向您的项目添加 C 和 C++ 代码

从当前的activity获得根视图

getWindow().getDecorView()

无标题风格

在指定的activity中设定 android:theme=”@style/Theme.AppCompat.Light.NoActionBar”

Android实现无标题栏全屏的三种方法
You need to use a Theme.AppCompat theme (or descendant) with this activity.

【Android 应用开发】 ActionBar 基础

Android存储访问及目录

Android中的Environment.getExternalStorageState使用

Android实现简单音乐播放器(MediaPlayer)
MediaPlayer播放音频与视频

Gson使用指南

JSON (官网) 是一种文本形式的数据交换格式,它比XML更轻量、比二进制容易阅读和编写,调式也更加方便。其重要性不言而喻。解析和生成的方式很多,Java中最常用的类库有:JSON-Java、Gson、Jackson、FastJson等。

期望的json格式

1
{"name":"怪盗kidou","age":24,"emailAddress":"ikidou@example.com"}

实际

1
{"name":"怪盗kidou","age":24,"email_address":"ikidou@example.com"}

这对于使用PHP作为后台开发语言时很常见的情况,php和js在命名时一般采用下划线风格,而Java中一般采用的驼峰法,让后台的哥们改吧 前端和后台都不爽,但要自己使用下划线风格时我会感到不适应,怎么办?难到没有两全齐美的方法么?

我们知道Gson在序列化和反序列化时需要使用反射,说到反射就不得不想到注解,一般各类库都将注解放到annotations包下,打开源码在com.google.gson包下果然有一个annotations,里面有一个SerializedName的注解类,这应该就是我们要找的。

那么对于json中email_address这个属性对应POJO的属性则变成:

1
2
@SerializedName("email_address")
public String emailAddress;

这样的话,很好的保留了前端、后台、Android/java各自的命名习惯。

你以为这样就完了么?

如果接中设计不严谨或者其它地方可以重用该类,其它字段都一样,就emailAddress 字段不一样,比如有下面三种情况那怎么?重新写一个?

1
2
3
{"name":"怪盗kidou","age":24,"emailAddress":"ikidou@example.com"}
{"name":"怪盗kidou","age":24,"email_address":"ikidou@example.com"}
{"name":"怪盗kidou","age":24,"email":"ikidou@example.com"}

为POJO字段提供备选属性名
SerializedName注解提供了两个属性,上面用到了其中一个,别外还有一个属性alternate,接收一个String数组。
注:alternate需要2.4版本

1
2
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;

当上面的三个属性(email_address、email、emailAddress)都中出现任意一个时均可以得到正确的结果。
注:当多种情况同时出时,以最后一个出现的值为准。

1
2
3
4
Gson gson = new Gson();
String json = "{\"name\":\"怪盗kidou\",\"age\":24,\"emailAddress\":\"ikidou_1@example.com\",\"email\":\"ikidou_2@example.com\",\"email_address\":\"ikidou_3@example.com\"}";
User user = gson.fromJson(json, User.class);
System.out.println(user.emailAddress); // ikidou_3@example.com

你们要的多数据库功能终于来了

数据库框架LitePal使用指南
Android数据库高手秘籍(四)——使用LitePal建立表关联

TouchListener PK OnTouchEvent + 多点触碰

TouchListener是基于监听的,而OnTouchEvent则是基于回调的!
OnTouchListener相关方法与属性

1
2
3
4
5
onTouch(View v, MotionEvent event):这里面的参数依次是触发触摸事件的组件,触碰事件event 封装了触发事件的详细信息,同样包括事件的类型、触发时间等信息。比如event.getX(),event.getY()
我们也可以对触摸的动作类型进行判断,使用event.getAction( )再进行判断;如:
event.getAction == MotionEvent.ACTION_DOWN:按下事件
event.getAction == MotionEvent.ACTION_MOVE:移动事件
event.getAction == MotionEvent.ACTION_UP:弹起事件

onTouchEvent更多的是用于自定义的view,所有的view类中都重写了该方法,而这种触摸事件是基于回调的,也就是说:如果我们返回的值是false的话,那么事件会继续向外传播,由外面的容器或者Activity进行处理!当然还涉及到了手势(Gesture),这个我们会在后面进行详细的讲解!onTouchEvent其实和onTouchListener是类似的,只是处理机制不用,前者是回调,后者是监听模式!

多点触碰

多点触碰就是多个手指在屏幕上进行操作,用的最多的估计是放大缩功能吧,比如很多的图片浏览器都支持缩放!理论上Android系统本身可以处理多达256个手指的触摸,当然这取决于手机硬件的支持;不过支持多点触摸的手机一般支持2-4个点,当然有些更多!我们发现前面两点都有用到MotionEvent,MotionEvent代表的是一个触摸事件;前我们可以根据event.getAction() & MotionEvent.ACTION_MASK来判断是哪种操作,除了上面介绍的三种单点操作外,还有两个多点专用的操作:
MotionEvent.ACTION_POINTER_DOWN:当屏幕上已经有一个点被按住,此时再按下其他点时触发。
MotionEvent.ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)。

简单的流程大概是这样:
当我们一个手指触摸屏幕 ——> 触发ACTION_DOWN事件
接着有另一个手指也触摸屏幕 ——> 触发ACTION_POINTER_DOWN事件,如果还有其他手指触摸,继续触发
有一个手指离开屏幕 ——> 触发ACTION_POINTER_UP事件,继续有手指离开,继续触发
当最后一个手指离开屏幕 ——> 触发ACTION_UP事件
而且在整个过程中,ACTION_MOVE事件会一直不停地被触发
我们可以通过event.getX(int)或者event.getY(int)来获得不同触摸点的位置: 比如event.getX(0)可以获得第一个接触点的X坐标,event.getX(1)获得第二个接触点的X坐标这样… 另外,我们还可以在调用MotionEvent对象的getPointerCount()方法判断当前有多少个手指在触摸~

Bitmap(位图)全解析

Drawable:通用的图形对象,用于装载常用格式的图像,既可以是PNG,JPG这样的图像, 也是前面学的那13种Drawable类型的可视化对象!我们可以理解成 一个用来放画的——画框
Bitmap(位图):我们可以把他看作 一个画架,我们先把画放到上面,然后我们可以 进行一些处理,比如获取图像文件信息,做旋转切割,放大缩小等操作
Canvas(画布):如其名,画布,我们可以在上面作画(绘制),你 既可以用Paint(画笔), 来画各种形状或者写字,又可以用Path(路径)来绘制多个点,然后连接成各种图形!
Matrix(矩阵):用于图形特效处理的,颜色矩阵(ColorMatrix),还有 使用Matrix进行图像的 平移,缩放,旋转,倾斜等
而上述的这些都是Android中的底层图形类:android.graphics给我们提供的接口

Drawable资源使用注意事项

Drawable分为两种: 一种是我们普通的图片资源,在Android Studio中我们一般放到res/mipmap目录下, 和以前的Eclipse不一样哦!另外我们如果把工程切换成Android项目模式,我们直接 往mipmap目录下丢图片即可,AS会自动分hdpi,xhdpi…! 另一种是我们编写的XML形式的Drawable资源,我们一般把他们放到res/drawable目录 下,比如最常见的按钮点击背景切换的Selctor!

在XML我们直接通过@mipmap或者@drawable设置Drawable即可 比如: android:background = “@mipmap/iv_icon_zhu” / “@drawable/btn_back_selctor” 而在Java代码中我们可以通过Resource的getDrawable(R.mipmap.xxx)可以获得drawable资源 如果是为某个控件设置背景,比如ImageView,我们可以直接调用控件.getDrawale()同样 可以获得drawable对象!

Android中drawable中的资源名称有约束,必须是:[a-z0-9_.](即:只能是字母数字及和.), 而且不能以数字开头,否则编译会报错: Invalid file name: must contain only [a-z0-9.]! 小写啊!!!!小写!!!小写!——重要事情说三遍~

圆形图片CircleImageView的使用和分析

Android CircleImageView圆形ImageView
CircleImageView项目下载地址:
https://github.com/hdodenhof/CircleImageView

自定义属性attrs:

1
2
3
4
5
6
<declare-styleable name="CircleImageView">
<attr name="civ_border_width" format="dimension" />
<attr name="civ_border_color" format="color" />
<attr name="civ_border_overlay" format="boolean" />
<attr name="civ_fill_color" format="color" />
</declare-styleable>

属性介绍:civ_border_width: 设置边框的宽度,默认为0,即无边框。
civ_border_color: 设置边框的颜色,默认为黑色。
civ_border_overlay:设置边框是否覆盖在图片上,默认为false,即边框在图片外圈。
civ_fill_color: 设置图片的底色,默认透明。
注意:CircleImageView的默认ScaleType为CENTER_CROP,且只能为CENTER_CROP。

Limitations

  1. The ScaleType is always CENTER_CROP and you’ll get an exception if you try to change it. This is (currently) by design as it’s perfectly fine for profile images.
  2. Enabling adjustViewBounds is not supported as this requires an unsupported ScaleType
  3. If you use an image loading library like Picasso or Glide, you need to disable their fade animations to avoid messed up images. For Picasso use the noFade() option, for Glide use dontAnimate(). If you want to keep the fadeIn animation, you have to fetch the image into a Target and apply a custom animation yourself when receiving the Bitmap.
  4. Using a TransitionDrawable with CircleImageView doesn’t work properly and leads to messed up images.

三个绘图工具类

Drawable以及Bitmap,都是加载好图片的,而本节我们要学习的绘图相关的 一些API,他们分别是Canvas(画布),Paint(画笔),Path(路径)!本节非常重要,同时也是我们 自定义View的基础

Intent之复杂数据的传递

Android 基础入门教程

Intent传递数组

写入数组

1
bd.putStringArray("StringArray", new String[]{"呵呵","哈哈"});

//可把StringArray换成其他数据类型,比如int,float等等…
读取数组

1
String[] str = bd.getStringArray("StringArray")

Intent传递集合

List<基本数据类型或String>
写入集合:
intent.putStringArrayListExtra(name, value)
intent.putIntegerArrayListExtra(name, value)
读取集合:
intent.getStringArrayListExtra(name)
intent.getIntegerArrayListExtra(name)

List< Object>
将list强转成Serializable类型,然后传入(可用Bundle做媒介)
写入集合:
putExtras(key, (Serializable)list)
读取集合:
(List) getIntent().getSerializable(key)
PS:Object类需要实现Serializable接口

MediaPlayer播放音频与视频

Android多媒体中的——MediaPlayer,我们可以通过这个API来播放音频和视频 该类是Androd多媒体框架中的一个重要组件,
通过该类,我们可以以最小的步骤来获取,解码 和播放音视频。它支持三种不同的媒体来源:

  1. 本地资源
  2. 内部的URI,比如你可以通过ContentResolver来获取
  3. 外部URL(流) 对于Android所支持的的媒体格式列表

Android小项目之“音乐播放器”
设置播放器的监听器:
MediaPlayer提供了一些设置不同监听器的方法来更好地对播放器的工作状态进行监听,以期及时处理各种情况,
如: setOnCompletionListener(MediaPlayer.OnCompletionListener listener)、
setOnErrorListener(MediaPlayer.OnErrorListener listener)等,设置播放器时需要考虑到播放器可能出现的情况设置好监听和处理逻辑,以保持播放器的健壮性。

安装Apache服务器

一句话,通过官方网站和集成包,最为简单快捷
XAMPP Apache + MariaDB + PHP + Perl

上传文件到7牛,删除后服务器未能及时刷新

如果调试需要,只能重命名后再上传,更换新的路径

JAVA中,字符串拼接尽量使用StringBuilder的append方法

效率测试可参看java五种拼接字符串的方法

“”和null的差别

s是一个String类的引用,null表示它不指向任何字符串对象,””表示s指向一个长度为0的字符串对象。如果调用s.length()之类的方法,s为null时会抛出NullPointerException,而””则能进行正常的计算。

模拟器离线

通过DDMS的File Explorer查看文件提示
com.android.ddmlib.AdbCommandRejectedException: device offline

【解决办法】在cmd下输入:
Step1: adb kill-server
Step2: adb start-server
或者打开进程管理器,把adb关掉,再重启adb。

button透明

1
2
半透明<Button android:background="#11000000" />
透明<Button android:background="#00000000" />

原理:颜色和不透明度 (alpha) 值以十六进制表示法表示。任何一种颜色的值范围都是 0 到 255(00 到 ff)。对于 alpha,00 表示完全透明,ff 表示完全不透明。表达式顺序是“aabbggrr”,其中“aa=alpha”(00 到 ff);“bb=blue”(00 到 ff);“gg=green”(00 到 ff);“rr=red”(00 到 ff)。所以要实现半透明只需将‘bb’,‘gg’,‘rr’的值都设为‘00’,只调节‘aa’的值(00到方法)就可以控制不同的透明度。

按钮点击效果变化

android selector 背景选择器的使用, button (未点击,点击,选中保持状态)效果实现
Android Button、ImageView等自定义选中、按下、未选中等效果

android获取string.xml的值

更多参考:android获取string.xml的值
获取string.xml文件里面的值有几个不同的地方。
1.在AndroidManifest.xml与layout等xml文件里:
android:text=”@string/resource_name”

2.在activity里:
方法一:this.getString(R.string.resource_name);
方法二:getResources().getString(R.string.resource_name);

3.在其他java文件(必须有Context或pplication)
方法一: context.getString(R.string.resource_name);
方法二: application.getString(R.string.resource_name);

Android Button、ImageView等自定义选中、按下、未选中等效果

原文
方法:自定义状态效果可以通过代码实现,也可以通过xml定义style实现。
android selector 背景选择器的使用, button (未点击,点击,选中保持状态)效果实现

升级到AndroidStudio2.3之后,添加ListView控件,程序异常

原因:ListView控件使用了MATCH_PARENT,而该属性在ConstraintLayout布局中是不支持的
Exception raised during rendering: MATCH_PARENT is not supported in ConstraintLayout (Details) Tip: Try to refresh the layout.

解决方案:去除该属性,或者改成LinearLayout
提前检测:通过“Design”预览,看能否正常显示出来,如果不能,详细分析其警告信息

新建资源文件目录问题

res目录下,新建layout目录文件,不能解析控件,在layout目录下,也不能新建目录,提示其只支持xml文件

AndroidStudio2.3不能显示logcat的问题

可以通过Restart logging来恢复,另外,充分利用选中进程、filter和日志级别来第一时间找出有用的日志信息。