《手机卫士》随听笔记:


防止子控件抢占父控件焦点:

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:

registerForContextMenu(listviewname or gridviewname);
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
@Override
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) {}


一个ListView,动态设置适配器:

adapter = new AppManagerAdapter(userAppinfos,AppManagerActivity.this);//参数分别为适配器填充内容的list表和上下文

lv.setAdapter(adapter);


获取手机当前正在运行的程序的包名:

ActivityManageram = (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的操作

使用staticview对象的应用减少内存中申请的局部变量的个数

//分批的加载数据

//分页的加载数据

//懒加载


锁屏时定义对应操作:

<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){

//得到类的简写名称 System.out.println(sample.class.getSimpleName()); //得到对象的全路径 System.out.println(sample.class); //得到对象的类模板示例,也就是Class System.out.println(sample.class.getClass()); //得到Class类的名称 System.out.println(sample.class.getClass().getName()); } } 打印结果为: sample class com.lovo.test.sample class java.lang.Class java.lang.Class
scrollView滚到最后:

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.HttpClient
DefaultHttpClient 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 点击事件分发小计:

[置顶] Android 《手机卫士》随听笔记_第1张图片


更多相关文章

  1. Android进程so注入Hook java方法
  2. Android JNI使用方法
  3. Android 布局中的android:onClick的使用方法总结
  4. SSH服务器与Android通信(2)--Android客户端接收数据
  5. 在Android中创建和使用数据库
  6. Android工程手动增加插件包方法
  7. android颜色值的表示方法android:background="#FFFFFFFF"的意思
  8. Android 使用Vitamio打造自己的万能播放器(4)――本地播放(快捷搜索
  9. android设置横屏和竖屏的方法

随机推荐

  1. Android(安卓)ANR:Application Not Respon
  2. 使用Android(安卓)SDK 的核心自带的资源
  3. Android让Fragment加载到Activity中
  4. 使用库项目实现Android程序代码的复用
  5. 白话文--Android热修复
  6. 【微博客】开复老师微博想到的
  7. 转:APK Crack
  8. Android(安卓)实现登录界面和功能实例
  9. Android(安卓)动画之补间动画
  10. Android切图注意事项