《手机卫士》随听笔记:
防止子控件抢占父控件焦点:
android:descendantFocusability="blocksDescendants"
加layout和不加的区别:
padding_top 控件里面的内容距离控件边框的距离
layout_margaintop 控件与控件之间的距离·
android:gravity:设置的是控件自身上面的内容位置
android:layout_gravity:设置控件本身相对于父控件的显示位置。
splash全屏显示:
// 取消标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 取消状态栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
Ps: 也可以通过主题设置窗体全屏显示
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
pull解析器使用:
XmlPullParser parser = Xml.newPullParser();
UpdataInfo info = new UpdataInfo();//info为一实例,里面包含字段:version、description、apkurl
parser.setInput(is, "utf-8"); //is为inputstream文件输入流
int type = parser.getEventType();
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
case XmlPullParser.START_TAG:
if("version".equals(parser.getName())){
String version = parser.nextText();
info.setVersion(version);
}else if("description".equals(parser.getName())){
String description = parser.nextText();
info.setDescription(description);
}else if("apkurl".equals(parser.getName())){
String apkurl = parser.nextText();
info.setApkurl(apkurl);
}
break;
}
type = parser.next();
}
return info;
联网获取服务器返回的输入流:
String path = "服务器下载path";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(2000);
conn.setRequestMethod("GET");
InputStream is = conn.getInputStream();
将输入流转化为字符串:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = (is.read(buffer))) != -1) {
bos.write(buffer, 0, len);
}
bos.flush();
bos.close();//关闭是无效的,因为它操作的都是内存中数据,不需要释放资源
is.close();
bos.toString();
或者
new String(bos.toByteArray());
}
获取程序版本号:
PackageManager manager = getPackageManager();
PackageInfo info = manager.getPackageInfo(getPackageName(), 0);
info.versionName;//得到版本号
安装APK:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");//file为apk位置
startActivity(intent);
对话框:
AlertDialog.Builder buider = new Builder(this);//上下文
buider.setIcon(R.drawable.xxx);
buider.setTitle("xxx");
buider.setMessage("xxx");
buider.setCancelable(false); // 让用户按返回键不能取消对话框
buider.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
buider.setNegativeButton("取消", new DialogInterface.OnClickListener() {
});
buider.create().show();//不要忘记了
子线程里面通知主线程ui更新
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//根据子线程传过来的消息进行响应
msg.what//得到传过来的值
}
};
子线程发出通知:
new Thread(){
@Override
public void run() {
super.run();
handler.sendEmptyMessage(0);//无传递参数时
Message msg = new Message();//应该使用Message msg = Message.obtain();重复利用message
msg.what = 10;//msg.obj
handler.sendMessage(msg);
}
}.start();
判断SD卡是否可用:
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) //为true时可用
获得外存储设备的根目录:
Environment.getExternalStorageDirectory()
xml定义颜色渐变色:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://"
android:shape="rectangle" >
<!-- 长方形 -->
<!-- 边框颜色和宽度 -->
<stroke
android:width="0.5dip"
android:color="#ff9d9d9d" />
<!-- 边角变圆滑 -->
<corners android:radius="2dip" >
</corners>
<!-- 渐变色 -->
<gradient
android:centerColor="#ff262626"
android:endColor="#ff515151"
android:startColor="#ff2c2d2d" />
</shape>
xml颜色选择器selector,按下按钮变色:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://">
<item android:drawable="@drawable/button_background" android:state_enabled="true" android:state_window_focused="false"/>//可点,没获得焦点
<item android:drawable="@drawable/button_background_selected" android:state_pressed="true"/>//按下
<item android:drawable="@drawable/button_background" android:state_focused="true"/>//获取焦点
<item android:drawable="@drawable/button_background"/>//默认情况下
</selector>
自定义对话框样式:
<style name="MyDialog" parent="@android:style/Theme.Dialog">
<!-- 自定义背景 -->
<item name="android:windowBackground">@drawable/title_background</item>
<!-- 没有标题 -->
<item name="android:windowNoTitle">true</item>
</style>
自定义对话框的使用:
dialog = new Dialog(this, R.style.MyDialog);
dialog.setCancelable(false);
View view = View.inflate(this, R.layout.normal_entry_dialog, null);
Button bt_normal_ok = (Button) view.findViewById(R.id.bt_normal_dialog_ok);
Button bt_normal_cancle = (Button) view.findViewById(R.id.bt_normal_dialog_cancle);
bt_normal_ok.setOnClickListener(this);
bt_normal_cancle.setOnClickListener(this);
//dialog.setContentView(R.layout.first_entry_dialog);//不可以这样写,注册不上监听事件
dialog.setContentView(view);
dialog.show();
具体详细字段可用apktool反编译制定版本的android.jar文件的res/values/style.xml进行查询设置
在receiver和service组件中激活activity: 他们不存在任务栈
Intent intent = new Intent(context, LostProtectedActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 指定要激活的activity在自己的任务栈里面运行
context.startActivity(intent);
拦截拨打电话配置:
<receiver android:name=".receiver.CallPhoneReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
extends BroadcastReceiver类,在onReceive方法中String number = getResultData();得到导出的电话号码
设置切换界面动画(逐渐消失和出现):
overridePendingTransition(R.anim.alpha_in, R.anim.alpha_out);
alpha_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="300"
>
</alpha>
alpha.out.xml:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="300"
>
</alpha>
获取手机服务:
TelephonyManager manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
获取手机sim卡串号:
String simserial = manager.getSimSerialNumber();
SharedPreferences的使用:
private SharedPreferences sp;
sp = getSharedPreferences("config", Context.MODE_PRIVATE);
Editor editor = sp.edit();
editor.putString("sim", simserial);
editor.commit();//很重要
得到字段:sp.getString("sim",null);//默认为null
限定EditText只能输入指定文本:
android:digits="0123456789." //数字和"."
将xml文件转化为view对象:
inflater = LayoutInflater.from(context);
View.inflate(int resource,ViewGroup root);
联系人操作:
三张重要的表:1.data:存放电话等信息 2.raw_contacts:记录联系人id 3.mimetypes:定义联系人每项信息对应的数据类型
查询联系人操作:返回姓名和手机号:
public List<ContactInfo> getContactInfos() {
ContentResolver resolver = context.getContentResolver();
// 1.获取联系人的id
// 2.根据联系人的id 获取联系人名字
// 3.根据联系人的id 数据的type 获取到对应的数据(电话,email);
List<ContactInfo> infos = new ArrayList<ContactInfo>();
ContactInfo info;
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri datauri = Uri.parse("content://com.android.contacts/data");
Cursor cursor = resolver.query(uri, null, null, null, null);
while (cursor.moveToNext()) {
info = new ContactInfo();
String id = cursor.getString(cursor.getColumnIndex("_id"));
String name = cursor.getString(cursor.getColumnIndex("display_name"));
info.setName(name);
Cursor datacursor = resolver.query(datauri, null,"raw_contact_id=?", new String[] { id }, null);
while (datacursor.moveToNext()) {
// mimetype
String type = datacursor.getString(datacursor.getColumnIndex("mimetype"));
if ("vnd.android.cursor.item/phone_v2".equals(type)) {
String number = datacursor.getString(datacursor.getColumnIndex("data1"));
info.setPhone(number);
}
}
datacursor.close();
infos.add(info);
info = null;
}
cursor.close();
return infos;
}
获取activity的返回值
例如:A->B->A 即由A界面转向B界面,选择之后返回到A界面并且带回选择的值
首先A中:
Intent intent = new Intent(A.this, B.class);
startActivityForResult(intent, 0);//0为请求码,当请求多个activity返回值时使用
然后进入B:
Intent intent = new Intent();
intent.putExtra("number", phone);
setResult(0, intent);//0为返回码,当有多个activity有返回值时使用
finish();
最后返回到A界面:
重写方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data != null) {
String number = data.getStringExtra("number");
//得到了选择的值
}
}
14.04.17
终止广播:
abortBroadcast();
获取拦截的短信:
权限:<uses-permission android:name="android.permission.RECEIVE_SMS"/>
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
for (Object pdu : pdus) {
SmsMessage sms = SmsMessage.createFromPdu((byte[]) pdu);
String content = sms.getMessageBody();
Log.i(TAG, "短信内容" + content);
String sender = sms.getOriginatingAddress();//短信发送方
}
发送短信:
权限:<uses-permission android:name="android.permission.RECEIVE_SMS"/>
SmsManager smsmanager = SmsManager.getDefault();
smsmanager.sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent);
打电话:
Intent intent = new Intent(); // 意图 代表一个要执行动作的意图
intent.setAction(Intent.ACTION_CALL); //将ACTION_CALL换为ACTION_DIAL是跳转到拨号界面而不是直接拨打电话
intent.setData(Uri.parse("tel:" + number));
startActivity(intent);
简单播放音乐:
MediaPlayer player = MediaPlayer.create(context, R.raw.ylzs);//参数为上下文和资源id
player.setLooping(true);//设置是否循环
player.start();//开始播放
文本框为空时颤动:
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
et_number.startAnimation(shake);//et_number为晃动文本框的name
R.anim.shake:
<translate xmlns:android="htt://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0"
android:interpolator="@anim/cycle_7"
android:toXDelta="10" />
@anim/cycle_7:
<cycleInterpolator xmlns:android="htt://schemas.android.com/apk/res/android"
android:cycles="7" />
得到数据库访问对象Dao:
public static SQLiteDatabasegetAddressDB(String path){
return SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);
}
访问数据库,查询内容:
SQLiteDatabase db = AddressDao.getAddressDB("db路径");
if (db.isOpen()) {
Cursor cursor = db.rawQuery("select city from 表 where 字段=?",new String[] { number.substring(0, 7) });
if (cursor.moveToNext()) {
address = cursor.getString(0);//得到结果集第一列内容
}
cursor.close();
db.close();
}
插入内容:
SQLiteDatabase db = dbHelper.getWritableDatabase();
if (db.isOpen()) {
db.execSQL("insert into blacknumber (number) values (?)",new Object[] { number });
db.close();
}
手机号码正则表达式:
^1[3458]\\d{9}$
匹配regex:字段.matches(表达式) 返回Boolean值
电话服务使用:
配置: <service android:name=".service.AddressService">
类实现:
public class AddressService extends Service {
private TelephonyManager manager;
private MyPhoneListener listener;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
listener = new MyPhoneListener();
manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
manager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
private class MyPhoneListener extends PhoneStateListener{
// 电话状态发生改变的时候 调用的方法
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // 处于静止状态: 没有呼叫
break;
case TelephonyManager.CALL_STATE_RINGING: // 零响状态
Log.i(TAG,"来电号码为"+ incomingNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK: //接通电话状态
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
manager.listen(listener, PhoneStateListener.LISTEN_NONE);
listener = null;
}
}
单选框:
AlertDialog.Builder builder = new Builder(this);
builder.setTitle("xxx");
String[] items = new String[] { "半透明", "活力橙", "苹果绿" };
builder.setSingleChoiceItems(items, 0,new DialogInterface.OnClickListener() { //默认选中第一个条目
public void onClick(DialogInterface dialog, int which) {
}
});
builder.setPositiveButton("确定",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
builder.create().show();
通过布局 更改iv_drag_view在窗体中的位置
LayoutParams params = (LayoutParams) iv_drag_view.getLayoutParams();
params.leftMargin = x;
params.topMargin = y;
iv_drag_view.setLayoutParams(params);
创建数据库:
public class BlackNumberDBHelper extends SQLiteOpenHelper {
public BlackNumberDBHelper(Context context) {
super(context, "blacknumber.db", null, 1);
}
/**
* 第一次创建数据库的时候执行 oncreate方法
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE blacknumber (_id integer primary key autoincrement, number varchar(20))");
}
/**
* 更新数据库的操作
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
判断字符串是否为null或者长度为0:
TextUtils.isEmpty(number)//返回Boolean值
ListView防止闪烁:
在ListView节点下加上:android:cacheColorHint="@android:color/transparent"
弹出软键盘防止系统重新加载控件:
android:windowSoftInputMode="adjustPan"
防止键盘弹出将菜单栏挤出去:
先用scrollView包裹,再在manifest中activity节点下加上:
android:windowSoftInputMode="stateVisible|adjustResize"
让数据适配器通知listview更新数据
// 重新获取黑名单号码
numbers = dao.getAllNumbers();
//更新数据
adapter.notifyDataSetChanged();
Adapter. NotifydataSetChange(); // 通知数据适配器数据发生了改变 界面会刷新 刷新的位置 是在当前的位置
adapter.notifyDataSetInvalidated();//通知数据适配器数据发生了改变 界面会刷新 导致整个界面的刷新 回到顶部
选择菜单OptionsMenu:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO 自动生成的方法存根
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.bg:
break;
case R.id.text:
break;
}
return false;
}
上下文菜单Contextual Menus:
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
int id = (int) info.id;
switch (item.getItemId()) {
case R.id.update_number:
break;
case R.id.delete_number:
break;
}
return false;
}
context_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/update_number"
android:title="更改黑名单号码">
</item>
<item
android:id="@+id/delete_number"
android:title="删除黑名单号码">
</item>
</menu>
删除通话记录:
public void deleteCallLog(String number) {
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, null, "number=?", new String[]{number}, null);
if(cursor.moveToFirst()){//查询到了呼叫记录
String id =cursor.getString(cursor.getColumnIndex("_id"));
resolver.delete(CallLog.Calls.CONTENT_URI, "_id=?",new String[]{id});
}
}
内容观察者:
// 注册一个内容观察者 观察call_log的uri的信息
getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, true,new MyObserver(new Handler(), incomingNumber));//incomingNumber可无
private class MyObserver extends ContentObserver {
private String incomingnumber;
public MyObserver(Handler handler, String incomingnumber) {
super(handler);
this.incomingnumber = incomingnumber;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
deleteCallLog(incomingnumber);
// 当删除了呼叫记录后 反注册内容观察者
getContentResolver().unregisterContentObserver(this);
}
}
状态栏通知notification:
// 1. 获取notification的管理服务
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// 2 .把一个要想显示的notification 对象创建出来,一闪而过
int icon = R.drawable.notification;
CharSequence tickerText = "发现响一声号码";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
// 3 .配置点击notification后的一些参数
Context context = getApplicationContext();
CharSequence contentTitle = "响一声号码";
CharSequence contentText = incomingNumber;
notification.flags = Notification.FLAG_AUTO_CANCEL;
notification.vibrate = new long[] { 1000, 2000, 1000 };//加入权限 <uses-permission android:name="android.permission.VIBRATE"/>
Intent notificationIntent = new Intent(this, CallSmsActivity.class);//CallSmsActivity为点击后激活的界面
// 把响一声的号码 设置到intent对象里面
notificationIntent.putExtra("number", incomingNumber);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText,contentIntent);
// 4. 通过manger把notification 激活
manager.notify(0, notification);
在子线程中显示吐司:
Looper.prepare();
Toast.makeText(getApplicationContext(), "备份完成", 1).show();
Looper.loop();
写xml文件:
List<SmsInfo> smsinfos = smsInfoService.getSmsInfos();
File file = new File("/sdcard/smsbackup.xml");
XmlSerializer serializer = Xml.newSerializer();
FileOutputStream os = new FileOutputStream(file);
serializer.setOutput(os, "utf-8");
serializer.startDocument("utf-8", true);
serializer.startTag(null, "smss");
serializer.startTag(null, "count");
serializer.text(smsinfos.size()+"");
serializer.endTag(null, "count");
for(SmsInfo info : smsinfos){
serializer.startTag(null, "sms");
serializer.startTag(null, "id");
serializer.text(info.getId());
serializer.endTag(null, "id");
serializer.startTag(null, "address");
serializer.text(info.getAddress());
serializer.endTag(null, "address");
serializer.startTag(null, "date");
serializer.text(info.getDate());
serializer.endTag(null, "date");
serializer.startTag(null, "type");
serializer.text(info.getType()+"");
serializer.endTag(null, "type");
serializer.startTag(null, "body");
serializer.text(info.getBody());
serializer.endTag(null, "body");
serializer.endTag(null, "sms");
}
serializer.endTag(null, "smss");
serializer.endDocument();
//把文件缓冲区的数据写出去
os.flush();
os.close();
读xml文件,并将读到的内容写入短信数据库:
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new FileInputStream("/sdcard/smsbackup.xml"), "utf-8");
int type = parser.getEventType();
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
case XmlPullParser.START_TAG:
if ("sms".equals(parser.getName())) {
values = new ContentValues();
} else if ("id".equals(parser.getName())) {
values.put("id", parser.nextText());
} else if ("address".equals(parser.getName())) {
values.put("address", parser.nextText());
} else if ("data".equals(parser.getName())) {
values.put("data", parser.nextText());
} else if ("type".equals(parser.getName())) {
values.put("type", parser.nextText());
} else if ("body".equals(parser.getName())) {
values.put("body", parser.nextText());
}
break;
case XmlPullParser.END_TAG:
if ("sms".equals(parser.getName())) {
System.out.println(values);
}
}
type = parser.next();
}
获取本地信息内容:
List<SmsInfo> smsInfos = new ArrayList<SmsInfo>();
ContentResolver resolver = context.getContentResolver();
Uri uri = Uri.parse("content://sms/");
Cursor cursor = resolver.query(uri, new String[] { "_id", "address","date", "type", "body" }, null, null, "date desc");
SmsInfo smsinfo;
while (cursor.moveToNext()) {
String id = cursor.getString(0);
String address = cursor.getString(1);
String date = cursor.getString(2);
int type = cursor.getInt(3);
String body = cursor.getString(4);
smsinfo = new SmsInfo(id, address, date, type, body);
smsInfos.add(smsinfo);
smsinfo = null;
}
return smsInfos;
添加类似toast之类的显示框:
WindowManager.LayoutParams params = new LayoutParams();
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.format = PixelFormat.TRANSLUCENT;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.setTitle("Toast");
params.gravity = Gravity.LEFT | Gravity.TOP;
View view = View.inflate(getApplicationContext(),cn.itcast.mobilesafe.R.layout.show_location, null);//获取显示的布局文件
LinearLayout ll = (LinearLayout) view.findViewById(R.id.ll_location);
TextView tv = (TextView) view.findViewById(R.id.tv_location);//显示的文字
tv.setTextSize(24);
tv.setText(address);
windowmanager.addView(view, params);
LIstView条目之间分割线:
android:divider="#ffff0000"
android:dividerHeight="2px"
获取手机安装的app程序:
private PackageManager packmanager;
public List<AppInfo> getAllApps() {
List<AppInfo> appinfos = new ArrayList<AppInfo>();
List<PackageInfo> packinfos = packmanager.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);//获取所有的app信息
for (PackageInfo info : packinfos) {
AppInfo myApp = new AppInfo();
String packname = info.packageName;// 获取包名字,卸载时可用到
myApp.setPackname(packname);
ApplicationInfo appinfo = info.applicationInfo;//获取application节点下的信息
Drawable icon = appinfo.loadIcon(packmanager);//app图标
myApp.setIcon(icon);
String appname = appinfo.loadLabel(packmanager).toString();// 得到application名字
myApp.setAppname(appname);
if (filterApp(appinfo)) {
myApp.setSystemApp(false);//第三方软件
} else {
myApp.setSystemApp(true);//系统软件
}
appinfos.add(myApp);
}
return appinfos;
}
判断是否为系统App:
public boolean filterApp(ApplicationInfo info) {
if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
return true;
} else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
return true;
}
return false;
}
当有多个view对象时,可以设置标志:
v.setTag(position);
通过v.getTag();得到标志。。。。。。。。。
在本APP开启另一个程序App:
packname = "App 包名";
PackageInfo info = getPackageManager().getPackageInfo(packname,PackageManager.GET_UNINSTALLED_PACKAGES| PackageManager.GET_ACTIVITIES);
ActivityInfo[] activityinfos = info.activities;
if (activityinfos.length > 0) {
ActivityInfo startActivity = activityinfos[0];
Intent intent = new Intent();
intent.setClassName(packname, startActivity.name);
startActivity(intent);
}else {
Toast.makeText(this, "当前应用程序无法启动", 0).show();
}
弹出小框框localPopupWindow:
// 获取当前view对象在窗体中的位置
int[] arrayOfInt = new int[2];
view.getLocationInWindow(arrayOfInt);
int i = arrayOfInt[0] + 60;
int j = arrayOfInt[1];
localPopupWindow = new PopupWindow(popupview,LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// 不显示设定背景时,一定要记得给popupwindow设置背景颜色
// Drawable background = new ColorDrawable(Color.TRANSPARENT);
Drawable background = getResources().getDrawable(R.drawable.local_popup_bg);
localPopupWindow.setBackgroundDrawable(background);
localPopupWindow.showAtLocation(view, Gravity.LEFT| Gravity.TOP, i, j);//view为要挂载到的对象
消灭小框框localPopupWindow:
dismissPopUpwindow();
渐现动画:
ScaleAnimation sa = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
sa.setDuration(200);
ll.startAnimation(sa);
分享功能实现:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain"); // 需要指定意图的数据类型
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享1");
shareIntent.putExtra(Intent.EXTRA_TEXT,"推荐你使用一个程序");
shareIntent = Intent.createChooser(shareIntent, "分享2");//分享2为分享对话框上方显示的文字
startActivity(shareIntent);
卸载程序:
String uristr = "package:" + packname;
Uri uri = Uri.parse(uristr);
Intent deleteIntent = new Intent();
deleteIntent.setAction(Intent.ACTION_DELETE);
deleteIntent.setData(uri);
startActivityForResult(deleteIntent, 0);
调用startActivityForResult(deleteIntent, 0);之后可以可以调用以下方法更新UI:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {}
adapter = new AppManagerAdapter(userAppinfos,AppManagerActivity.this);//参数分别为适配器填充内容的list表和上下文
lv.setAdapter(adapter);
获取手机当前正在运行的程序的包名:
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> taskinfos = am.getRunningTasks(1);
RunningTaskInfo currenttask = taskinfos.get(0);// 获取当前用户可见的activity 所在的程序的包名
String packname = currenttask.topActivity.getPackageName();
Log.i(TAG, "当前运行" + packname);
添加震动效果:
import android.app.Service;
Vibrator vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);
vibrator.vibrate(new long[] { 0, 500 }, -1);//0表示立即震动 -1为不返回值
权限:<uses-permission android:name="android.permission.VIBRATE" />
按下返回键进行相应的操作:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
return true; // 阻止按键事件继续向下分发
}
return super.onKeyDown(keyCode, event);
}
listview的优化
复用convertview 减少getview方法对Inflater的操作
使用static的view对象的应用 减少内存中申请的局部变量的个数
//分批的加载数据
//分页的加载数据
// 懒加载
锁屏时定义对应操作:
<receiver android:name=".receiver.LockScreenReceiver" >
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
</receiver>
public class LockScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//在屏幕锁屏的时候 会调用这个onReceve 方法
}
}
自定义标题;
boolean flag = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
if (flag) {
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.mytitle);
}
获取手机制造商版本号等信息:android.os.Build
杀死应用程序:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
am.killBackgroundProcesses(Packname());
/**
* 获取当前系统的剩余的可用内存信息 byte long
*/
private long getAvailMemoryInfo() {
MemoryInfo outInfo = new ActivityManager.MemoryInfo();
am.getMemoryInfo(outInfo);
return outInfo.availMem;
}
自定义吐司:
public class MyToast {
public static void showToast(Context context, int iconid, String text) {
View view = View.inflate(context, R.layout.my_toast, null);
TextView tv = (TextView) view.findViewById(R.id.tv_my_toast);
ImageView iv = (ImageView) view.findViewById(R.id.iv_my_toast);
iv.setImageResource(iconid);
tv.setText(text);
Toast toast = new Toast(context);
toast.setDuration(0);
toast.setView(view);
toast.show();
}
}
自定义吐司显示:
MyToast.showToast(this, R.drawable.notification, "自定义吐司显示");
通过反射技术获得android系统隐藏掉的方法:
1.以下实例为获得类android.widget.AppSecurityPermissions下的getPermissionsView方法,他没有参数
try {
Class clazz = getClass().getClassLoader().loadClass("android.widget.AppSecurityPermissions");
Constructor constructor = clazz.getConstructor(new Class[] {Context.class, String.class });//获得构造方法,上下文 包名
Object object = constructor.newInstance(new Object[] { this,"cn.itcast.mobilesafe" });//获得cn.itcast.mobilesafe的信息
Method method = clazz.getDeclaredMethod("getPermissionsView",new Class[] {});
View view = (View) method.invoke(object, new Object[] {});//通过invoke()方法执行,传入对象,方法无参数传入
} catch (Exception e) {
e.printStackTrace();
}
}
2.通过反射调用PackageManager类中的抽象方法getPackageSizeInfo,传入的参数为 packname,new IPackageStatsObserver.Stub(){}
Method method = PackageManager.class.getMethod("getPackageSizeInfo", new Class[] { String.class,IPackageStatsObserver.class });
method.invoke(pm, new Object[] { packname,new IPackageStatsObserver.Stub() {
public void onGetStatsCompleted(PackageStats pStats,boolean succeeded) throws RemoteException {}
}});
application全局整个程序context上下文共享文件:
1.在根节点包下建立class:
public class MyApplicationextends Application {
public TaskInfo taskinfo;//在application所有的activity中都可以访问到taskinfo对象
}
2.清单文件配置:application节点下:
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:name="MyApplication">
..................
3.在activity中使用:
MyApplication myapp = (MyApplication) getApplication();
TaskInfo taskinfo = myapp.taskinfo;//获取到taskinfo
...............//操作
myapp.taskinfo = null;//释放掉内存
TextView隐藏下面的横线:
android:background="@null"
获取当前时间:
String am_or_pm = "上午 ";
final Calendar c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
String mYear = String.valueOf(c.get(Calendar.YEAR)); // 获取当前年份
String mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
if (mMonth.length() == 1) {
mMonth = "0" + mMonth;
}
String mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码
String mWay = String.valueOf(c.get(Calendar.DAY_OF_WEEK));
String mAm_Pm = String.valueOf(c.get(Calendar.AM_PM));
String mHuor = String.valueOf(c.get(Calendar.HOUR));
if (mHuor.length() == 1) {
mHuor = "0" + mHuor;
}
String mMinute = String.valueOf(c.get(Calendar.MINUTE));
if (mMinute.length() == 1) {
mMinute = "0" + mMinute;
}
if ("1".equals(mWay)) {
mWay = "日";
} else if ("2".equals(mWay)) {
mWay = "一";
} else if ("3".equals(mWay)) {
mWay = "二";
} else if ("4".equals(mWay)) {
mWay = "三";
} else if ("5".equals(mWay)) {
mWay = "四";
} else if ("6".equals(mWay)) {
mWay = "五";
} else if ("7".equals(mWay)) {
mWay = "六";
}
if ("1".equals(mAm_Pm)) {
am_or_pm = "下午";
}
String time = mYear + "年" + mMonth + "月" + mDay + "日" + " 星期" + mWay
+ " " + am_or_pm + mHuor + ":" + mMinute;
获取简单时间方法:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(new Date());
由资源id获得Drawable对象:
Drawable picture = this.getResources().getDrawable(R.drawable.ic_launcher);
当有多个模拟器时进入指定设备终端:
adb -s 设备名称 shell
手机流量小知识:
1.cmd -> adb shell -> cd proc -> cd uid_stat -> ls-l
2.cmd -> adb root -> adb shell -> cd data ->cd data -> ls-l
两个步骤得到结果的后两位比对得到app所对应的uid
说明:
步骤1得到的为每个app对应这个应用程序上传和下载产生的流量信息 包名为uid cd进去 有:
tcp_rcv:采用tcp协议 接收到的数据的大小 tcp receive
tcp_snd:采用tcp协议 发送的数据的byte大小 snd send
tcp_rcv_pkt:采用tcp协议 接收到的包的数目
流量信息 :上一次开机到现在这个程序产生的流量
注意:模拟器是不支持流量查询的
获取手机上传下载流量API: android.net.TrafficStats;
获取在桌面产生图标的应用信息:
PackageManager pm = getPackageManager();
Intent intent = new Intent();
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.LAUNCHER");
List<ResolveInfo> activities = pm.queryIntentActivities(intent,PackageManager.GET_RESOLVED_FILTER);
实现抽屉功能:
<SlidingDrawer
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:content="@+id/content"
android:handle="@+id/handle"
android:orientation="vertical" >
<ImageView
android:id="@id/handle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<ListView
android:id="@id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>
</SlidingDrawer>
给listview增加上下标题:
lv.addFooterView(View.inflate(this, R.layout.title, null));
lv.addHeaderView(View.inflate(this, R.layout.title, null));
图片大小重新设置:
public class ImageUtil {
/**
* 返回一个宽度和高度都为48个像素的bitmap
* @param drawable
* @return
*/
public static Bitmap getResizedBitmap(BitmapDrawable drawable,
Context context) {
Bitmap bitmap = drawable.getBitmap();
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
int height = display.getHeight();
int width = display.getWidth();
if (height <= 480 || width <= 320) {
return Bitmap.createScaledBitmap(bitmap, 32, 32, false);
} else {
return Bitmap.createScaledBitmap(bitmap, 100, 100, false);
}
}
}
定时器的简单使用:
private Timer adapter;
private TimerTask task;
private Timer timer;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
adapter.notifyDataSetChanged();
}
};
@Override
protected void onStart() {
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
// 发送一个消息给主线程
Message msg = Message.obtain();
handler.sendMessage(msg);
}
};
timer.schedule(task, 1000, 2000);
super.onStart();
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
timer.cancel();
timer = null;
task = null;
}
一个activity若有以下节点
<intent-filter>
<action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
可以这样激活:
Intent intent = new Intent();
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("package"+pname));
startActivity(intent);
将src目录下文件(如,数据库)复制到SD卡:
private void copyfile() {
try {
InputStream is = getClass().getClassLoader().getResourceAsStream("clearpath.db");
OutputStream fos = this.openFileOutput("clearpath.db", MODE_PRIVATE);
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
递归删除目录:
private void deleteDir(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
deleteDir(file);
}
} else {
file.delete();
}
}
ProgressBar的简单应用:
private ProgressBar pb = (ProgressBar) this.findViewById(R.id.progressBar);
pb.setMax(infos.size());
pb.setProgress(total);
Map的应用:
private Map<String, CacheInfo> maps;
maps = new HashMap<String, CacheInfo>();
maps.put(packname, cacheinfo);
将maps集合转化为list表:
private Set<Entry<String, CacheInfo>> sets;
private List<CacheInfo> cacheinfos;
sets = maps.entrySet();
cacheinfos = new ArrayList<CacheInfo>();
for (Entry<String, CacheInfo> entry : sets) {
cacheinfos.add(entry.getValue());
}
listview增加快速滑块及修改滑块图像:
lv.setFastScrollEnabled(true);
Field field = AbsListView.class.getDeclaredField("mFastScroller");
field.setAccessible(true);
Object obj = field.get(lv);
field = field.getType().getDeclaredField("mThumbDrawable");
field.setAccessible(true);
Drawable drawable = (Drawable) field.get(obj);
drawable = getResources().getDrawable(R.drawable.book);
field.set(obj, drawable);
list排序:books为 private List<BookInfo> books;
Comparator comp_bid_up = new Comparator() {public int compare(Object o1, Object o2) {
BookInfo p1 = (BookInfo) o1;
BookInfo p2 = (BookInfo) o2;
if (Integer.parseInt(p1.getBid()) < Integer.parseInt(p2
.getBid()))
return -1;
else if (Integer.parseInt(p1.getBid()) == Integer
.parseInt(p2.getBid()))
return 0;
else if (Integer.parseInt(p1.getBid()) > Integer
.parseInt(p2.getBid()))
return 1;
return 0;
}
};
Collections.sort(books, comp_bid_up);
就这么简单就将books按照bid升序排列,并将排序后的结果放在了books中。
保存图片到sdka:
public void saveFile(String savepath, Bitmap bm, String fileName)
throws IOException {
File dirFile = new File(savepath);
if (!dirFile.exists()) {
dirFile.mkdir();
}
File myCaptureFile = new File(savepath + fileName);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(myCaptureFile));
bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);
bos.flush();
bos.close();
}
simpleCursorAdapter 的使用:在列表中显示联系人和手机号码
Uri uri = Uri.parse("content://com.android.contacts/data/phones");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
// 绑定数据 必须返回一个_id字段
@SuppressWarnings("deprecation")
SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_expandable_list_item_2, cursor,
new String[] { "display_name", "data1" }, new int[] {android.R.id.text1, android.R.id.text2 });
lv.setAdapter(simpleCursorAdapter);
向系统数据库中添加联系人:
public void insertContacts(String name, String number) {
ContentValues cv = new ContentValues();
Uri rawContactUri = getContentResolver().insert(
RawContacts.CONTENT_URI, cv);
long rawContactsId = ContentUris.parseId(rawContactUri);
cv.clear();
cv.put(StructuredName.RAW_CONTACT_ID, rawContactsId);
cv.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
cv.put(StructuredName.DISPLAY_NAME, name);
// 插入联系人姓名等信息
getContentResolver().insert(Data.CONTENT_URI, cv);
cv.clear();
cv.put(Phone.RAW_CONTACT_ID, rawContactsId);
cv.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
cv.put(Phone.NUMBER, number);
getContentResolver().insert(Data.CONTENT_URI, cv);
}
res目录和assets目录主要有以下两个区别:
1.获取res目录中的资源需要使用R类中的资源ID,如:
InputStream is = getResources().openRawResource(R.raw.ic_launcher);
Bitmap bm = BitmapFactory.decodeStream(is);
iv.setImageBitmap(bm);
而获取asserts中的资源只需要文件名,如下面获取图片的代码:
InputStream is = getResources().getAssets().open("ic");
Bitmap bm = BitmapFactory.decodeStream(is);
iv.setImageBitmap(bm);
2.res目录中只能建立相应资源的目录,有:drawable、values、layout、xml、animal、raw、animator。
不能建立其他任何目录,也不能建立二级和多级目录。而asserts目录可以建立任意多级目录。
Bitmap转Drawable:
Bitmap bm=xxx; //xxx根据你的情况获取
BitmapDrawable bd=new BitmapDrawable(bm);
Drawable转Bitmap:
Drawable d=xxx; //xxx根据自己的情况获取drawable
BitmapDrawable bd = (BitmapDrawable) d;
Bitmap bm = bd.getBitmap();
自定义进度条:定义的是进度条显示的视觉效果
drawble下clip.xml:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="horizontal"
android:drawable="@drawable/progress"
android:gravity="left" >
</clip>
在布局文件中加入image标签,背景设置为clip
<ImageView
android:id="@+id/iv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/clip" />
现在就可以使用了:
ImageView iv = (ImageView) findViewById(R.id.iv);
ClipDrawable drawable = (ClipDrawable) iv.getBackground();
drawable.setLevel(level);//level范围:0-10000
网络专用:把一个inputstream里面的内容转化成一个byte[]
public static byte[] getBytes(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer))!=-1){
bos.write(buffer, 0, len);
}
is.close();
bos.flush();
byte[] result = bos.toByteArray();
System.out.println(new String(result));
return result;
}
public static void main(String[] args){
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
两种方式请求服务器并获得返回值:
1.URLConnection
try {String result = "", str = "";
URL url = new URL("");
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
InputStreamReader inputStreamReader = new InputStreamReader(
connection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
while ((str = bufferedReader.readLine()) != "") {
result += str;
}
} catch (IOException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
2.HttpClientDefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("");
ResponseHandler<String> responseHandler = new BasicResponseHandler();
try {
String result = client.execute(httpGet, responseHandler);
} catch (ClientProtocolException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
} catch (IOException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
2015.12.04 点击事件分发小计: