Splash界面
splash: 溅,洒
展现产品的logo提升产品的知名度 初始化操作(创建 数据库 ,读取配置文件) 连接服务器检查软件授权 连接服务器检查软件的更新自动更新的前提
包名一致 签名一致状态选择器
整体取消掉标题栏:在清单文件中加一修改主题
android:theme=”@android:style/Theme.Light.NoTitleBar”
PackageManager:获取各种包的信息(版本、应用程序图标、包信息等)
开源项目框架:
xUtils-2.6.8.jar 断点下载
使用:
1
2
3
4
5
6
7
8
9
10
11
12
|
HttpUtils httputils=
new
HttpUtils();
httputils.download(url,target,autoResume,callback);
//url:下载的路径
//targer:存放的路径sd
//autoResume:true是否断点续传
//callback:下载回传
new
RequestCallBack<file>(){
重写onSuccess();
重写onFailure();
重写onload();
//显示下载进度在textview中当前/总进度
}
</file>
|
开源项目断点下载xUtils耗时操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
HttpUtils http=
new
HttpUtils();
final
File file=
new
File(Environment.getExternalStorageDirectory(),
"xxx.apk"
);
http.download(data.downLoadUrl, file.getAbsolutePath(),
true
,
new
RequestCallBack<file>(){
//下载失败
@Override
public
void
onFailure(HttpException arg0, String arg1) {
}
//下载成功
@Override
public
void
onSuccess(ResponseInfo arg0) {
//下载成功,替换安装模板代码
ToastUtils.show(SplashActivity.
this
,
"下载成功"
);
Intent intent=
new
Intent();
intent.setAction(
"android.intent.action.VIEW"
);
intent.addCategory(
"android.intent.category.DEFAULT"
);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive"
);
startActivity(intent);
}});
</file>
|
1
2
3
4
5
|
Itent intent=
new
Intent();
intent.setAction(
"android.intent.action.VIEW"
);
intent.addCategory(
"android.intent.category.DEFAULT"
);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive"
);
startActivity(intent);
|
市面上常用界面-九宫格
状态选择器:
就是在res目录下建立一个drawable文件中定义一个xml文件,设置属性background时引用这个xml文件就行。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//背景颜色选择
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<item android:drawable=
"@android:color/darker_gray"
android:state_pressed=
"true"
>
//按住时
<item android:drawable=
"@android:color/darker_gray"
android:state_focused=
"true"
>
//聚焦时
<item android:drawable=
"@android:color/transparent"
>
//默认状态
</item>
</item>
</item>
</selector>
|
按住图标显示不一样的图片,新建一个tupian.xml文件,引用图标时R.drawable.tupian.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//图标状态选择
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<item android:drawable=
"@drawable/app_pressed"
android:state_pressed=
"true"
>
//按住时
<item android:drawable=
"@drawable/app_focused"
android:state_focused=
"true"
>
//聚焦时
<item android:drawable=
"@drawable/app"
>
//默认状态
</item>
</item>
</item>
</selector>
|
走马灯效果按钮
Button可实现,当点击按钮的时候滚动起来
设置属性
1
2
3
|
android:focusableInTouchMode=
"true"
android:ellipsize=
"marquee"
android:text=
"显示的内容"
|
TextView也可以实现滚动走马灯:需要自定义TextView,实现里面的所有构造函数并重写isFocused()直接返回true
1
2
3
4
5
|
@Override
@ExportedProperty
(category =
"focus"
)
public
boolean
isFocused() {
return
true
;
}
|
并设置下面几个属性
1
2
|
<com.cca.mobilephone.ui.focusedtextview android:ellipsize=
"marquee"
android:focusableintouchmode=
"true"
android:layout_height=
"wrap_content"
android:layout_width=
"match_parent"
android:singleline=
"true"
android:text=
"希望我所认识的亲戚朋友远离病痛,远离饥饿,走上富康的道路,过上幸福的的生活!"
>
</com.cca.mobilephone.ui.focusedtextview>
|
这样textview跑马灯效果就可以跑起来了
设置一条线可以使用View
自定义组合控件:textView+checkBox 下面还有一条分割线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
class
SettingCheckView
extends
LinearLayout {
public
SettingCheckView(Context context, AttributeSet attrs) {
super
(context, attrs);
initial(context);
String bigtitle=attrs.getAttributeValue(
"http://schemas.android.com/apk/res/com.cca.mobilephone"
,
"bigtitle"
);
TextView tv_title=(TextView) findViewById(R.id.tv_ui_setting);
tv_title.setText(bigtitle);
}
public
SettingCheckView(Context context) {
super
(context);
initial(context);
}
private
void
initial(Context context) {
this
.setOrientation(LinearLayout.VERTICAL);
//
this
.addView(View.inflate(context, R.layout.ui_setting_view,
null
));
}
}
|
布局文件:
1
2
3
4
5
6
7
8
9
10
|
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<relativelayout android:background=
"@drawable/background"
android:id=
"@+id/rl_set_update"
android:layout_gravity=
"center_vertical"
android:layout_height=
"50dp"
android:layout_width=
"match_parent"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<textview android:id=
"@+id/tv_ui_setting"
android:layout_centervertical=
"true"
android:layout_height=
"wrap_content"
android:layout_marginleft=
"10dp"
android:layout_width=
"match_parent"
android:text=
"开启自动更新"
android:textsize=
"20sp"
>
<checkbox android:clickable=
"false"
android:focusable=
"false"
android:id=
"@+id/cb_set_update"
android:layout_alignparentright=
"true"
android:layout_centervertical=
"true"
android:layout_height=
"wrap_content"
android:layout_marginright=
"20dp"
android:layout_width=
"wrap_content"
>
<view android:background=
"#88000000"
android:layout_height=
"0.1dp"
android:layout_margin=
"2dp"
android:layout_width=
"match_parent"
>
</view></checkbox></textview></relativelayout>
|
使用时:
1
2
|
<com.cca.mobilephone.ui.settingcheckview android:layout_height=
"wrap_content"
android:layout_width=
"match_parent"
mobilephone:bigtitle=
"我是功能2"
>
</com.cca.mobilephone.ui.settingcheckview>
|
自定义属性:
先声明属性命名空间
1
|
xmlns:mobilephone=
"http://schemas.android.com/apk/res/com.cca.mobilephone"
|
在values定义一个attrs.xml文件,在里面声明功能
1
2
3
4
5
6
7
8
9
10
11
|
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<resources>
<declare-styleable name=
"SettingCheckView"
>
</attr></declare-styleable>
//或者
<declare-styleable name=
"SettingCheckView"
>
</attr></declare-styleable>
</resources>
|
做到这里就可以使用自定义组合控件了,功能可以设置文本内容,想增加其他的属性,在attrs中定义出来就可以使用了。
自定义对话框:
1
2
3
4
|
AlertDialog.Builder builder=
new
Builder(context);
View dialogview=View.inflate(context, R.layout.show_setup_dialog,
null
);
builder.setView(view);
builder.show();
|
//高低版本默认的背景色和字体颜色不一样、使高低版本保持一致的样式需
设置其背景色、文本字体色
1
2
3
4
5
|
AlertDialog.Builder builder=
new
Builder(MainActivity.
this
);
View dialogview=View.inflate(context, R.layout.show_setup_dialog,
null
);
AlertDialog dialog=builder.create();
dialog.setView(dialogview,
0
,
0
,
0
,
0
);
//设置对话框上下左右的距离
dialog.show();
|
show_setup_dialog的xml布局文件如下:
1
2
3
4
5
6
|
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<linearlayout android:layout_height=
"wrap_content"
android:layout_width=
"300dp"
android:orientation=
"vertical"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<textview android:background=
"#BFFF01"
android:gravity=
"center"
android:layout_height=
"wrap_content"
android:layout_width=
"match_parent"
android:text=
"设置密码"
android:textsize=
"30dp"
>
<edittext android:gravity=
"center_horizontal"
android:hint=
"请输入密码"
android:inputtype=
"textPassword"
android:layout_height=
"wrap_content"
android:layout_marginleft=
"5dp"
android:layout_marginright=
"5dp"
android:layout_width=
"300dp"
>
<edittext android:gravity=
"center_horizontal"
android:hint=
"请确定密码"
android:inputtype=
"textPassword"
android:layout_height=
"wrap_content"
android:layout_marginleft=
"5dp"
android:layout_marginright=
"5dp"
android:layout_width=
"300dp"
>
<linearlayout android:layout_height=
"wrap_content"
android:layout_width=
"300dp"
><button android:background=
"@drawable/btn_background"
android:layout_height=
"wrap_content"
android:layout_marginright=
"5dp"
android:layout_weight=
"1"
android:layout_width=
"0dp"
android:text=
"取消"
></button><button android:background=
"@drawable/btn_background"
android:layout_height=
"wrap_content"
android:layout_marginleft=
"5dp"
android:layout_weight=
"1"
android:layout_width=
"0dp"
android:text=
"确定"
></button></linearlayout></edittext></edittext></textview></linearlayout>
|
自定义背景选择器:btn_background.xml(要放在drawable文件下)
1
2
3
4
5
6
7
8
9
10
|
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<item android:drawable=
"@android:color/holo_blue_light"
android:state_pressed=
"true"
>
<item android:drawable=
"@android:color/holo_blue_light"
android:state_focused=
"true"
>
<item android:drawable=
"@android:color/transparent"
>
</item></item></item>
</selector>
|
当有很多个界面有相同的方法,相同的布局时,都要存储数据时,可定义一个父类让其他的类来继承它
动画的切换效果:
1
2
|
//一句代码,必须要放在Activity或者finish()的后面
overridePendingTransition(R.anim.trans_next_in, R.anim.trans_next_out);
|
在res目录下建立一个anim文件夹:创建两个xml:trans_next_in.xml和trans_next_out.xml如下
1
2
3
4
5
6
7
8
|
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<translate android:duration=
"300"
android:fromxdelta=
"100%p"
android:fromydelta=
"0"
android:toxdelta=
"0"
android:toydelta=
"0"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
</translate>
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<translate android:duration=
"300"
android:fromxdelta=
"0"
android:fromydelta=
"0"
android:toxdelta=
"-100%p"
android:toydelta=
"0"
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
</translate>
|
手势识别器
1、先声明一个手势识别器
1
|
private
GestureDetector mGestureDetector;
|
2、初始化一个手势识别器
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
|
//2、初始化手势识别器
mGestureDetector=
new
GestureDetector(getApplicationContext(),
new
GestureDetector.SimpleOnGestureListener(){
@Override
public
boolean
onFling(MotionEvent e1, MotionEvent e2,
float
velocityX,
float
velocityY) {
/**
* e1、手指触摸屏幕的一瞬间
* e2、手指离开屏幕的一瞬间
* velocityX、velocityY:水平方向和竖直方向的速度
*
*/
if
((e1.getRawX()-e2.getRawX())>
150
){
showNext();
overridePendingTransition(R.anim.trans_next_in, R.anim.trans_next_out);
return
true
;
}
if
((e2.getRawX()-e1.getRawX())>
150
){
showPre();
overridePendingTransition(R.anim.trans_pre_in, R.anim.trans_pre_out);
return
true
;
}
return
super
.onFling(e1, e2, velocityX, velocityY);
}
});
|
3、第三步、使用户识别手势器的动作
1
2
3
4
5
6
|
//第三步、使用手势识别器识别用户的动作
@Override
public
boolean
onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return
super
.onTouchEvent(event);
}
|
绑定手机卡、获取手机序列号,一个手机号对应一个序列号
1
2
3
4
|
//用到一个系统的服务
private
TelephonyManager tm=(TelephonyManager)
this
.getSystemService(Context.TELEPHONY_SERVICE);
//获取手机序列号
String sim=tm.getSimSerialNumber();
|
电话联系人
data/data/com.android.providers.contacts.database.contacts2.db
对应三张表:
查找联系人工具类:
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
|
public
class
ContactsInfoUtils {
public
static
List<contactsinfo> getContactsInfo(Context context){
List<contactsinfo> infocontacts=
new
ArrayList<contactsinfo>();
//获取内容提供者的解析器
ContentResolver resolver=context.getContentResolver();
//游标
Cursor cursor=resolver.query(uri,
new
String[]{
"contact_id"
},
null
,
null
,
null
);
//遍历游标集合
while
(cursor.moveToNext()){
String id=cursor.getString(
0
);
System.out.println(
"id"
+id);
ContactsInfo infos=
new
ContactsInfoUtils().
new
ContactsInfo();
Cursor datacursor=resolver.query(dataUri,
new
String[]{
"data1"
},
"raw_contact_id=?"
,
null
,
null
);
while
(datacursor.moveToNext()){
String data1=datacursor.getString(
0
);
String mimetype=datacursor.getString(
1
);
if
(
"vnd.android.cursor.item/name"
.equals(mimetype)){
//姓名
infos.name=data1;
}
else
if
(
"vnd.android.cursor.item/phone_v2"
.equals(mimetype)){
//电话
infos.phone=data1;
}
else
if
(
"vnd.android.cursor.item/email_v2"
.equals(mimetype)){
//电话
infos.email=data1;
}
}
infocontacts.add(infos);
}
return
infocontacts;
}
public
class
ContactsInfo{
public
String name;
public
String email;
public
String phone;
}
}
</contactsinfo></contactsinfo></contactsinfo>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
static
String encode(String text){
try
{
MessageDigest digest=MessageDigest.getInstance(
"md5"
);
String password=
"234"
;
byte
[] result=digest.digest(password.getBytes());
StringBuffer sb=
new
StringBuffer();
for
(
byte
b:result){
String hex=Integer.toHexString(b&
0xff
)+
2
;
//加盐更好更安全
if
(hex.length()==
1
){
sb.append(
"0"
);
}
sb.append(hex);
}
return
sb.toString();
}
catch
(NoSuchAlgorithmException e) {
e.printStackTrace();
return
""
;
}
}
|
播放报警音乐:便捷方式:src下新建目录raw可放音乐文件
1
2
3
4
5
6
7
8
|
MediaPlayer mediaplayer=MediaPlayer.create(context, R.raw.uri);
//循环播放
mediaplayer.setLooping(
true
);
//设置音量最大声
mediaplayer.setVolume(
1
.0f,
1
.0f);
mediaplayer.start();
abortBroadcast();
|
超级管理员:
Android 2.2引入了支持企业应用程序提供Android设备管理API。设备管理API提供了设备管理功能在系统水平。这些api允许您创建安全性敏感的应用程序是有用的在企业环境中,IT专业人员需要丰富的控制员工的设备。例如,内置Android电子邮件应用程序利用了新的api来改善交流的支持。通过电子邮件应用程序,交流管理员可以执行密码策略——包括字母数字密码或数字针——在设备。管理员也可以远程擦除(即恢复工厂默认值)丢失或被盗的手机。用户可以同步他们的电子邮件和日历数据交换。
Email client
Security application that to remove wipe
Device management service and application
一键锁屏应用:能够一键锁屏,一键卸载
步骤:
1、先创建admim类继承DeviceAdminReceiver
2、配置清单文件(参考api文档)
1
2
3
4
5
6
7
8
|
<receiver android:description=
"@string/sample_device_admin_description"
android:label=
"@string/sample_device_admin"
android:name=
"com.cca.yijian.Admin"
android:permission=
"android.permission.BIND_DEVICE_ADMIN"
>
<!-- 元数据,提供设备的超级管理员的配置信息 -->
<meta-data android:name=
"android.app.device_admin"
android:resource=
"@xml/device_admin_sample"
>
<intent-filter>
</action></intent-filter>
</meta-data></receiver>
|
还要新建一个 res目录下xml文件夹并新建device_admin_sample.xml:
声明中使用的安全策略的元数据提供了特定于设备管理员的附加信息,可通过DeviceAdminInfo类进行解析查看,以下为device_admin_sample.xml:的内容
1
2
3
4
5
6
7
8
9
10
11
12
|
<uses-policies>
<limit-password>
<watch-login>
<reset-password>
<force-lock>
<wipe-data>
<expire-password>
<encrypted-storage>
<disable-camera>
</disable-camera></encrypted-storage></expire-password></wipe-data></force-lock></reset-password></watch-login></limit-password></uses-policies>
</device-admin>
|
3、主活动中书写代码
点击按钮一键锁屏:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
void
lockscreen(View view){
DevicePolicyManager dpm=(DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
ComponentName who=
new
ComponentName(
this
, Admin.
class
);
if
(dpm.isAdminActive(who)){
//重置密码
//dpm.resetPassword("123", 0);
//清除sd卡数据
//dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);
dpm.lockNow();
finish();
}
else
{
Toast.makeText(
this
,
"请先激活应用程序"
,
0
).show();
}
}
|
使用时:先来到系统设置界面,找到安全、进入设备管理器、找到一键锁屏,点击激活一键锁屏,此时可以使用了。
先激活应用程序
给用户一个很好的体验:来个按钮“先激活应用程序”
1
2
3
4
5
6
|
Intent intent =
new
Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
ComponentName who=
new
ComponentName(
this
, Admin.
class
);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, who);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"请大家赶紧去激活程序吧,首次激活有大礼包!"
);
startActivity(intent);
|
一键卸载
再来个卸载按钮:
1
2
3
4
5
6
7
8
9
10
|
public
void
deleteLockScreen(View view){
DevicePolicyManager dpm=(DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
ComponentName who=
new
ComponentName(
this
, Admin.
class
);
dpm.removeActiveAdmin(who);
Intent intent=
new
Intent();
intent.setAction(Intent.ACTION_DELETE);
intent.setData(Uri.parse(
"package:"
+getPackageName()));
startActivity(intent);
}
|
获取位置的经纬度(真实标准坐标)在中国要转换成火星坐标才能真正确定位置
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
|
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取位置内容提供者
LocationManager lm=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria=
new
Criteria();
//指定高精度
criteria.setAccuracy(Criteria.ACCURACY_FINE);
//指定高耗电量
criteria.setPowerRequirement(Criteria.POWER_HIGH);
//获取最好的内容提供者
String provider =lm.getBestProvider(criteria,
true
);
lm.requestLocationUpdates(provider,
0
,
0
,
new
LocationListener() {
//状态改变时调用
@Override
public
void
onStatusChanged(String provider,
int
status, Bundle extras) {
}
//可用时调用
@Override
public
void
onProviderEnabled(String provider) {
}
@Override
public
void
onProviderDisabled(String provider) {
}
@Override
public
void
onLocationChanged(Location location) {
location.getLatitude();
//纬度
location.getLongitude();
//经度
System.out.println(
"纬度:"
+location.getLatitude()+
"------经度:"
+location.getLongitude());
TextView text=
new
TextView(getApplication());
text.setTextColor(Color.RED);
text.setText(
"纬度:"
+location.getLatitude()+
"------经度:"
+location.getLongitude());
}
} );
}
|
标准坐标—->>中国的火星坐标
使用算法:导入modifyOffset.java和axisoffset.dat
直接到代码中使用:
1
2
3
4
5
6
7
8
9
10
|
ModifyOffset no =ModifyOffset.getInstance(context.getClassLoader().getResourceAsStream(
"axisoffset.dat"
));
//真实坐标X经度 Y为纬度
//不过查找时外国网站经度放在围纬度后面:纬度,经度
PointDouble pt =
new
PointDouble(x,y);
PointDouble marpoint=mo.s2c(pt);
System.out.println(marpoint.toString());
//输出的是x=。。。。,y=。。。。。经纬度
|
listView的简单优化
容易内存溢出
1、尽量复用convertview历史的缓存,减少创建新的view对象
2、尽量的减少子孩子的id的查询次数,定义一个viewHolder
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
View view;
viewHolder holder;
if
(convertView!=
null
){
//复用历史的view对象
view=convertView;
holder=(viewHolder) view.getTag();
}
else
{
//创建新的孩子时加上标签
holder=
new
viewHolder();
view=View.inflate(getApplicationContext(), R.layout.item_callsmssafe,
null
);
holder.black_phone=(TextView) view.findViewById(R.id.tv_black_phone);
holder.black_mode=(TextView) view.findViewById(R.id.tv_black_mode);
view.setTag(holder);
}
//内部类
class
viewHolder{
public
TextView black_phone;
public
TextView black_mode;
public
ImageView black_delete;
}
|
listView显示数据库中的数据时,当listview发生变化时应更新listview数据
1
2
|
//通知listview更新数据
adapter.notifyDataSetChanged();
|
在清单文件中配置广播接收者的特点是:不管应用程序进程是否存在都能接受到对应广播