0%

启动图标

  • hdpi 72*72
  • mdpi 48*48
  • xhdpi 96*96
  • xxhdpi 144*144
  • xxxhdpi 192*192

参考网址

使用过的操作符

  • concat 连接多个Observables(被观察者)
    concat
    最多有9个参数,但是可以嵌套,传的数据必须是相同类型
  • mergeDelayError 合并发送
    MergeDelayError
    合并两个发送,如果一个出错不马上发送错误,而是延时到都发送完
  • interval 定时循环发送
    interval
  • map 数据类型转换(同步)
    map
  • flatmap 传入数据,生成新的Observable,一般处理异步任务,连接能实现concat功能
    flatmap
  • distinct 过滤去重操作符
    distinct
  • distinct(Func1) 自定义过滤操作符
    distintF1
    可以以其中的某个重复项为过滤条件
  • repeat 重复发送
    repeat
    重复订阅
  • retry 错误重试
    retry
    发送一个错误(onError),重新订阅
  • retryWhen(Func1) 判断错误,根据错误(func1)决定是否重新订阅
    retryWhen
    发送一个错误(onError),通过func1处理错误,决定是否再次订阅
  • Timeout 超时发送一个onError
    Timeout
  • zip 组合
    zip
  • zipwith 组合
    zipwith
    两个都发送onnext后组合,如果另外一个未发,等待组合后才开始发下一个
  • delay 延时发送
    delay

button点击事件

1
2
3
4
5
6
7
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

}
});
button.performClick(); //触发点击事件

从上面代码理解:
被观察者Observable—–>button—–>一些操作,事件,任务(相当于我们不知道button什么时候被点击)
观察者Observer/Subscriber—–>OnClickListener—–>决定事件触发的时候将有怎样的行为
订阅Subscribe—–>setOnClickListener—–>注册事件关联
事件onNext()/onCompleted()/onError()—–>onClick()—–>回调,最终结果(Subscriber多了onStart()``unsubscribe())

Observable 被观察者

创建被观察者

  • creat() 最基本的创造事件序列的方法
1
2
3
4
5
6
7
8
9
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("Hi");
subscriber.onNext("Aloha");
subscriber.onCompleted();
}
});
  • just() 快捷创建事件序列
1
2
3
4
5
6
Observable observable = Observable.just("Hello", "Hi", "Aloha");
// 将会依次调用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
  • from() 传入的数组或 Iterable 拆分成具体对象后,依次发送出来
1
2
3
4
5
6
7
String[] words = {"Hello", "Hi", "Aloha"};
Observable observable = Observable.from(words);
// 将会依次调用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
  • ActionX 自定义(onCompleted,onError,onNext) 无返回值
  • FuncX 有返回值
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
Action1<String> onNextAction = new Action1<String>() {
// onNext()
@Override
public void call(String s) {
Log.d(tag, s);
}
};
Action1<Throwable> onErrorAction = new Action1<Throwable>() {
// onError()
@Override
public void call(Throwable throwable) {
// Error handling
}
};
Action0 onCompletedAction = new Action0() {
// onCompleted()
@Override
public void call() {
Log.d(tag, "completed");
}
};

// 自动创建 Subscriber ,并使用 onNextAction 来定义 onNext()
observable.subscribe(onNextAction);
// 自动创建 Subscriber ,并使用 onNextAction 和 onErrorAction 来定义 onNext() 和 onError()
observable.subscribe(onNextAction, onErrorAction);
// 自动创建 Subscriber ,并使用 onNextAction、 onErrorAction 和 onCompletedAction 来定义 onNext()、 onError() 和 onCompleted()
observable.subscribe(onNextAction, onErrorAction, onCompletedAction);

Scheduler 线程控制(调度器)

  • Schedulers.immediate():直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler
  • Schedulers.newThread():总是启用新线程,并在新线程执行操作。
  • Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
  • Schedulers.computation():计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
  • AndroidSchedulers.mainThread():指定的操作将在 Android 主线程运行。
1
2
3
4
5
6
7
8
9
Observable.just(1, 2, 3, 4)
.subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
.observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer number) {
Log.d(tag, "number:" + number);
}
});

变换

  • map()
  • flatMap()

android 系统自带了文本转语音的功能

一般手机都有Pico TTS功能,但是没有中文语言包
解决方案: 安装google 语音装文本tts服务或者讯飞tts等兼容系统接口的TTs

文字转语音的代码比较少

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
TextToSpeech mTts;
mTts=new TextToSpeech(this, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
// status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
if (status == TextToSpeech.SUCCESS) {
// Set preferred language to US english.
// Note that a language may not be available, and the result will indicate this.
int result = mTts.setLanguage(Locale.CHINA);
// Try this someday for some interesting results.
// int result mTts.setLanguage(Locale.FRANCE);
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
// Lanuage data is missing or the language is not supported.
Log.e(TAG, "Language is not available.");
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
} else {
// Check the documentation for other possible result codes.
// For example, the language may be available for the locale,
// but not for the specified country and variant.
// The TTS engine has been successfully initialized.
// Allow the user to press the button for the app to speak again.
Log.i(TAG,"初始化成功");
mTts.speak("初始化成功",TextToSpeech.QUEUE_FLUSH,null);
}
} else {
// Initialization failed.
Log.e(TAG, "Could not initialize TextToSpeech.");
}
}
});

注意销毁 TextToSpeech

1
2
3
4
5
6
7
8
@Override
protected void onDestroy() {
super.onDestroy();
// 关闭TextToSpeech对象
if (mTts != null) {
mTts.shutdown();
}
}

问题

在使用nubia手机时,发现手机没有这项(TTs)设置,安装了其它TTs却不能开启。
解决:打算用第三方sdk,但是查了一下讯飞的离线文字转语音却发现是收费的,只能说nubia的系统太坑了。

端口

管理数据库,文件服务等端口,关闭了外部无法访问

  • 开启端口
1
firewall-cmd --zone=public --add-port=3306/tcp
  • 关闭端口
1
firewall-cmd --zone=public --remove-port=3306/tcp

系统开机启动项

/etc/rc.local

官方描述

设置边界

有时,通过移动摄像头来以尽可能最高的缩放级别显示整个受关注区域很有用处。 例如, 如果您要显示用户当前位置方圆五英里内的所有加油站, 可能就需要通过移动摄像头让它们全都显示在屏幕上。 如需实现此目的,请先计算您想在屏幕上显示的 LatLngBounds。 然后使用 CameraUpdateFactory.newLatLngBounds(LatLngBounds bounds, int padding) 获取 CameraUpdate,后者会相应更改摄像头位置,使得给定 LatLngBounds 在计入所指定内边距(单位:像素)后能够完全容纳在地图内。 返回的 CameraUpdate 可确保给定边界与地图边缘之间的间隙(单位:像素)至少与指定的内边距一样大。 请注意,地图的倾斜角度和方位均为 0。

1
2
3
4
5
6
7
8
private GoogleMap mMap;
// Create a LatLngBounds that includes Australia.
private LatLngBounds AUSTRALIA = new LatLngBounds(
new LatLng(-44, 113), new LatLng(-10, 154));

// Set the camera to the greatest possible zoom level that includes the
// bounds
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(AUSTRALIA, 0));

LatLngBounds

  • public LatLngBounds including (LatLng point) 包含显示的点
  • public LatLng getCenter () 获得中心点

代码的具体实现

1
2
3
4
5
LatLngBounds.Builder latLngBounds=new LatLngBounds.Builder();
for (int i=0;i<latLngs.size();i++){
latLngBounds.include(latLngs.get(i));
}
googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds.build(), 30));

问题

如果直接在获取到地图后调用会报错
解决:在回调里调用

1
2
3
4
5
googleMap.setOnMapLoadedCallback(this); 
@Override
public void onMapLoaded() {
//添加实现的代码
}

全局初始化greenDAO设置

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
public class UserGlobalApp extends Application{
private static UserGlobalApp application;
private final static String dbName = "HiJia"; //数据库名字
/** A flag to show how easily you can switch from standard SQLite to the encrypted SQLCipher. */
public static final boolean ENCRYPTED = false; //改为true需要加入包compile 'net.zetetic:android-database-sqlcipher:3.5.1'
private DaoSession daoSession;
@Override
public void onCreate() {
super.onCreate();
application=this;
initDb();
}

/***
* 初始化greenDao
* 数据库
*/
private void initDb(){
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, ENCRYPTED ? dbName+"-encrypted.db" : dbName+".db",null);
Database db = ENCRYPTED ? helper.getEncryptedWritableDb("super-secret") : helper.getWritableDb();
daoSession = new DaoMaster(db).newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}

public static UserGlobalApp getApplication(){
return application;
}
}

使用

添加数据,查询数据

1
2
3
UserGlobalApp.getApplication().getDaoSession().getTrackPointDao().insert(new TrackPoint((long) 10,System.currentTimeMillis(),10.01,10.02,1));
Log.i("sssss",""+UserGlobalApp.getApplication().getDaoSession().getTrackPointDao().loadAll().size());

生成的dao目录配置(非必须)

1
2
3
4
5
6
7
//------------greenDAO数据库配置-----------
greendao {
schemaVersion 1 //数据库版本
daoPackage'com.xuan.bledemo.db.greendao' //dao的存放目录
targetGenDir'src/main/java'
}

问题

数据库加密问题
在全局配置中如果要加密,要设置为true,但是设置为ture会报错

1
public static final boolean ENCRYPTED = false;  //改为true需要加入包compile 

解决:因为没有加密包,需要添加依赖

1
compile 'net.zetetic:android-database-sqlcipher:3.5.1'

数据库路径设置

1
2
3
File path=new File(Environment.getExternalStorageDirectory(),"BleDemo/db/"+dbName);  //设置存储路径
path.getParentFile().mkdirs();
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, ENCRYPTED ? path.getAbsolutePath()+"-encrypted.db" : path.getAbsolutePath()+".db",null);

新建一个xml,放标题内容

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary">
<!--自定义控件-->
<!--<TextView-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:text="标题" />-->
</android.support.v7.widget.Toolbar>

在需要的页面调用

1
2
3
4
<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="@layout/activity_tool_bar" />

去掉自带标题

在配置文件找到

1
android:theme="@style/AppTheme"

点击进去把parent修改为NoActionBar

1
2
3
4
5
6
7
8
9
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<!--最顶层的颜色消息时间栏-->
<item name="colorPrimary">@color/colorPrimary</item>
<!--标题栏颜色-->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!--应用内系统控件的颜色,例如系统的滑动条等-->
<item name="colorAccent">@color/colorAccent</item>
</style>

在activity里获取标题控件,设置基本属性

1
2
3
4
5
6
7
8
9
10
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("标题");
toolbar.setSubtitle("副标题");
toolbar.setTitleTextColor(Color.WHITE); //颜色
toolbar.setSubtitleTextColor(Color.WHITE);
toolbar.setLogo(R.mipmap.debug); //图标

//设置导航图标要在setSupportActionBar方法之后
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.mipmap.ic_launcher);

在activity添加标题栏返回箭头

使能返回button

1
2
3
4
5
6
7
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("标题");
toolbar.setSubtitle(副标题);
//设置导航图标要在setSupportActionBar方法之后
setSupportActionBar(toolbar);
if(getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); // Enable the Up button

添加返回button事件

1
2
3
4
5
6
7
8
9
 @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home: //返回键
//添加处理代码
break;
}
return super.onOptionsItemSelected(item);
}

扫描模式

ScanSettings的属性与方法

1
2
3
4
5
6
7
8
9
10
11
12
ScanSettings settings = new ScanSettings.Builder()
//设置扫描模式(SCAN_MODE_LOW_LATENCY扫描优先,SCAN_MODE_LOW_POWER省电优先,SCAN_MODE_BALANCED平衡模式,SCAN_MODE_OPPORTUNISTIC安卓6.0里面才用的模式)
.setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC)
//设置扫描的时间,设置了这一项,将扫描5秒,然后在onBatchScanResults里面回调
.setReportDelay(5000)
//android 6.0可用
.setMatchMode(1)
//android 6.0可用
.setCallbackType(1)
//android 6.0可用
.setNumOfMatches(1)
.build();

主流的ORM框架

greenDAO

介绍

greenDAO是一种Android数据库ORM(object/relational mapping)框架,与OrmLite、ActiveOrm、LitePal等数据库相比,单位时间内可以插入、更新和查询更多的数据,而且提供了大量的灵活通用接口。
源码github
官网

GreenDao 3.0改动:

使用过GreenDao的同学都知道,3.0之前需要通过新建GreenDaoGenerator工程生成Java数据对象(实体)和DAO对象,非常的繁琐而且也加大了使用成本。

GreenDao 3.0最大的变化就是采用注解的方式通过编译方式生成Java数据对象和DAO对象。