android 零星调试笔记
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android 零星调试笔记相关的知识,希望对你有一定的参考价值。
adb使用:
连接不上手机
C:\Users\Administrator\.android\adb_usb.ini 增加一行内容: 0x1782
2.安装系统应用
$ adb remount
$ adb push apk文件名 /system/app
// apk文件名形如testme.apk
卸载应用程序
1.$ adb uninstall 包名 例如:adb uninstall lee.study2. 在终端上找到:Home->设置->应用程序->管理应用程序->选择某应用程序->卸载
设置属性值
使用adb shell: 改成中文 setprop persist.sys.language zh;setprop persist.sys.country cn;stop;sleep 5;start
注解: setprop persist.sys.language zh(MCC: mobile country code);setprop persist.sys.country cn(MNC: mobile network code);
stop;sleep 5;start 延时5秒重启机器
查看系统定义所有权限列表:
adb shell pm list permissions
拨打电话: am start -a android.intent.action.CALL -d tel:10086 这里-a表示动作,-d表述传入的数据,还有-t表示传入的类型
打开网页: am start -a android.intent.action.VIEW -d http://www.baidu.com (这里-d表示传入的data)
打开音乐播放器: am start -a android.intent.action.MUSIC_PLAYER 或者 am start -n com.android.music/om.android.music.MusicBrowserActivity
启动服务: am startservice <服务名称>
例: am startservice -n com.android.music/com.android.music.MediaPlaybackService (这里-n表示组件)
am startservice -a com.smz.myservice (这里-a表示动作,就是你在Androidmanifest里定义的)
发送广播: am broadcast -a <广播动作> am broadcast -a android.intent.action.BOOT_COMPLETED
模拟按键
adb shell input keyevent 3 :模拟home键 3 = KeyEvent.KEYCODE_HOME
利用adb命令查看apk文件包名
在控制台输入命令$adb shell pm
可以看到adb shell pm的相关用法
要看一个apk文件的相关信息最简单实用的方法是:
aapt dump badging [app.apk]
如果只是想查看手机上应用的packageName,则输入命令:
adb shell pm list packages
如果想知道应用对应的apk文件在手机上的安装位置则可以在上面的命令后加-f参数
adb shell pm list packages -f
查看所有安装的apk包名:
adb shell ‘pm list packages -f‘ | sed -e ‘s/.*=//‘ | sort
adb server is out of date. killing... 解决措施:
描述:adb server is out of date. killing...
ADB server didn‘t ACK
* failed to start daemon *
error: unknown host service
究其源就是adb server没启动 解决过程分析整理如下:
E:\>adb nodaemon server
cannot bind ‘tcp:5037‘
原来adb server 端口绑定失败
继续查看到底是哪个端口给占用了
E:\>netstat -ano | findstr "5037"
TCP 127.0.0.1:4112 127.0.0.1:5037 CLOSE_WAIT 2960
TCP 127.0.0.1:5037 0.0.0.0:0 LISTENING 4596
TCP 127.0.0.1:5037 127.0.0.1:3006 ESTABLISHED 4596
TCP 127.0.0.1:6149 127.0.0.1:5037 CLOSE_WAIT 2960
打开任务管理器kill掉4596 这个进程。ok
解决读取权限问题
例如 使用adb push init.rc / 命令时报错:Unable to chmod init.rc: Read-only file system
在shell命令行中输入
adb root
切换到root用户
然后执行如下命令:(注意,/表示的是根目录,因此这个不仅仅是对sdcard,其他文件也可以读写。rw表示读写权限,mount重挂载文件系统)
adb shell mount -o remount rw /
执行完后,
可以用mount命令查看,当前挂载的文件系统权限如何,可以看出都有读写权限了(rw
代码中安装apk
Runtime.getRuntime().exec("pm install xxx.apk");
- /**
- * 安装apk
- * @param url
- */
- private void installApk(){
- File apkfile = new File(saveFileName);
- if (!apkfile.exists()) {
- return;
- }
- Intent i = new Intent(Intent.ACTION_VIEW);
- i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
- mContext.startActivity(i);
- }
Andoird判断某个APK是否已经安装
private boolean isAppInstalled(String uri){ PackageManager pm = getPackageManager(); boolean installed =false; try{ pm.getPackageInfo(uri,PackageManager.GET_ACTIVITIES); installed =true; }catch(PackageManager.NameNotFoundException e){ installed =false; } return installed; }
//Just call the method by passing the package name of the application you need to check.
if(isAppInstalled("com.yourpackage.package")){
//app installed
}else{
//app not installed
}
Logcat命令选项列表 选项 描述
[adb] logcat [<option>] ... [<filter-spec>] ...
options:
-b <buffer> 加载一个指定的LOG Buffer供查看,比如events 或radio。默认值是main 。具体参考查看指定的Log Buffers.
-c 清除整个 log并退出。
-d 输出LOG到屏幕上并退出。
-f <filename> 写LOG信息到 <filename>。默认是stdout.
-g 打印指定LOG Buffer的大小并退出。
-n <count> 设置日志的最大数目<count>,默认值是4,需要和选项-r一起使用。
-r <kbytes> Rotates每输出<kbytes> 写LOG文件,默认值为16,需要和选项-f一起使用。
-s 设置默认的过滤级别为silent。
-v <format> Sets 设置LOG的输出格式,默认的是brief 格式,要知道更多的支持的格式,参看控制LOG输出格式.
举例:
adb logcat ActivityManager:I MyApp:D *:S
只显示那些标签为“ActivityManager”且优先级为“Info”以上的和标签为“ MyApp”且优先级为“ Debug”以上的信息,其他标签的信息都不显示
表达式最后的元素 *:S,,是设置所有标签的优先级为“silent”,这样保证只有“ActivityManager”和“MyApp”的LOG才会显示
adb logcat -b <system,radio,events,main(default)>
main.log : adb logcat -v time >main.log
radio.log : adb logcat -b radio -v time>radio.log
net and routerinfo : adb shell ifconfig eth0>ifconfig.txt adb shell busybox route -n >route_info.txt
property value: adb shell getprop> no_services_sysprop.txt
iplog: adb shell tcpdump -i any -w /data/iplog.cap&adb pull data/iplog.cap
转: http://www.2cto.com/kf/201401/271875.html
log文件分为实时打印的,还有状态信息的两种
实时打印的主要有:logcat main,logcat radio,logcat events,tcpdump, QXDM Log
状态信息的有:adb shell dmesg,adb shell dumpstate,adb shell dumpsys,adb bugreport
实时log:
adb logcat -b events -v time 打印系统事件的日志,比如触屏事件
tcpdump 是很有用的,对于TCP/IP协议相关的都可以使用这个来抓,
adb shell tcpdump -s 10000 -w /sdcard/capture.pcap,
比如抓mms下载的时候的UA profile,browser上网的时候,使用proxy的APN下载,streaming的相关内容包括UA profile等。
状态log:
其实一个就够了,那就是bugreport(命令adb bugreport>bugreport.log)。
里面包含有dmesg,dumpstate和dumpsys;
dmesg(命令adb shell dmesg > ldmesg_kernel.log)是kernel的log,凡是跟kernel相关的,比如driver出了问题(相机,蓝牙,usb,启动,等等)
dumpstate是系统状态信息,里面比较全,包括手机当前的内存信息、cpu信息、logcat缓存,kernel缓存等等;
dumpsys这个是关于系统所有进程Process的内容都在这个里面,adb shell dumpsys 这个命令还有更详尽的用法,
比如adb shell dumpsys meminfo system是查看system这个process的内存信息。
dumpsys [options]
meminfo 显示内存信息
cpuinfo 显示CPU信息
account 显示accounts信息
activity 显示所有的activities的信息
window 显示键盘,窗口和它们的关系
wifi 显示wifi信息
通过adb logcat/bugreport可以实时的查看系统的log,以及系统的状态信息;
如何将Log存储下来,保存当时系统运行的情况呢?
可以通过一些脚本或者执行可执行程序来保存log信息,以便分析问题
命令参数:
名字 功能
account 显示accounts信息
activity 显示所有的activities的信息
cpuinfo 显示CPU信息
window 显示键盘,窗口和它们的关系
wifi 显示wifi信息
batteryinfo $package_name 电量信息及CPU 使用时长
package packagename 获取安装包信息
usagestats 每个界面启动的时间
statusbar 显示状态栏相关的信息
meminfo
内存信息(meminfo $package_name or $pid
使用程序的包名或者进程id显示内存信息)
diskstats 磁盘相关信息
battery 电池信息
alarm 显示Alarm信息
资源layout加载出错:
郁闷好久的问题: Android Error:main cannot be resolved or is not a fieldR.layout.main总是在layout上有错误提示波浪线。
解决方法:
(1) 删除"import android.R;".
(2) 勾选上Eclipse中的"Project->Build Automatically";
原因是:
添加文件,比如xml文件或者资源文件时,系统自动添加了import android.R;android.R是系统提供的资源,R是应用程序的资源。删除"import android.R"之后工程就是从/res文件夹下自动生成的资源文件里去解析了,否则它会从Android的资源类里去找。
Intent.ACTION_BOOT_COMPLETED 开机完成
模拟器启动不了
错误如 : Starting emulator for AVD ‘4.2.2‘ PANIC: Could not open: 4.2.2
解决:
1、把模拟器avd所在位置的.android文件夹直接复制C:\Documents and Settings\Administrator\
(模拟器avd所在位置 -- 选择 VIRTUAL... 选择安卓机,DETAILS...path:就是这个路径。把.android文件夹COPY到C:\Documents and Settings\Administrator\)
2、我的电脑-属性-高级 环境变量。
新建系统环境变量,
名字:ANDROID_SDK_HOME
变量值:X:\
X为android文件夹所在
(文件夹放在根目录)
然后新建一个,就能开机了
android彩蛋代码
DeviceInfoSettings.java ->onPreferenceTreeClick->
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("android", com.android.internal.app.PlatLogoActivity.class.getName());
startActivity(intent);
packages\apps\Crome\src\com\crome\test\PlatLogoActivity.java
取得屏幕大小:
1、在非activity类中WindowManager windowManager = (WindowManager)(mContext.getSystemService(Context.WINDOW_SERVICE));
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
2、在activity类中
int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); // 屏幕宽(像素,如:480px)
int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); // 屏幕高(像素,如:800px)
eclipse出现 Some characters cannot be mapped using "GBK" character encoding 错误代码的解决办法
今天在使用eclipse调试腾讯空间API时,在我更改APP key后,点击保存按钮时,出现了Some characters cannot be mapped using "GBK" character encoding 这样的错误代码,根据提示看,应该是说一些文字无法用GBK编码映射。应该是有些地方的文字编码设置成了GBK造成的。
马上google了一番,终于找到了解决的办法,依次点击Window->Profermance->General->Content Type->Text看目录下面的每个文件,包括子目录里面 Default encoding的值是否为utf-8,如果为别的值或为空,则全部改为utf-8,每一项改完,别忘了点一下update.全部改完后推出菜单,再点一下保存,终于成功了。
获得 LayoutInflater 实例的三种方式
1.LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater()2.LayoutInflater localinflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
3. LayoutInflater inflater = LayoutInflater.from(context);
示意代码:
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.custom, (ViewGroup)findViewById(R.id.test));
对于上面代码,指定了第二个参数 ViewGroup root,当然你也可以设置为 null 值。
ContentResolver.query(),以及 Activity.managedQuery异同:
参数、返回值相同:都返回 Cursor 对象参数:
URI: Content Provider 需要返回的资源索引
Projection: 用于标识有哪些columns需要包含在返回数据中。
Selection: 作为查询符合条件的过滤参数,类似于SQL语句中Where之后的条件判断。
SelectionArgs: 同上。
SortOrder: 用于对返回信息进行排序。
不同:
mContext.getContentResolver().query
ContentResolver.query(),以及 Activity.managedQuery()所以,我们看到一个是ContentResolver提供的查询方法,位于android.content.ContextWrapper.getContentResolver(),另一个则为Activity。 Activity.managedQuery() 方法导致活动管理 Cursor 的生命周期
硬件灭屏功能:写文件
"/sys/class/leds/lcd-backlight/brightness"./devices/platform/lcd-backlight/leds/lcd-backlight/brightness
0 :灭 255 : 亮
解锁功能
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("");
keyguardLock.disableKeyguard();
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
点亮屏幕
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);WakeLock mWakelock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP|PowerManager.SCREEN_DIM_WAKE_LOCK,"SimpleTimer");
mWakeLock.acquire();//点亮
mWakeLock.release();//关闭
activity全屏显示:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);requestWindowFeature(Window.FEATURE_NO_TITLE);
//注意;要在setContentView(R.layout.layout)语句之前调用才行
在最新SDK中随时可以改变改属性,做到随时隐藏、显示状态栏
private void showStatusBar(boolean bShow) { android.view.Window window = mActivity.getWindow(); android.view.WindowManager.LayoutParams lp = window.getAttributes(); int flag; if(window != null && lp != null){ if (bShow) { flag = lp.flags & ~android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; } else { flag = lp.flags | android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; } lp.flags = flag; window.setAttributes(lp); } }
取得build.prop中的值:
property_get()[c/c++] 、 SystemProperties_get*()[Java域]读取这些属性值 getBoolean、getInt、getLong、get
android 按键定义:
kernal\include\linux\input.h
设置默认动态墙纸:
在frameworks/base/core/res/res/values目录找到Config.xml文件<string name="default_wallpaper_component">@null</string>
将其修改为对应的live wallpaper的启动component即可,如要把默认壁纸设置为2.1自带的galaxy,这样写即可:<string name="default_wallpaper_component">com.android.wallpaper/com.android.wallpaper.galaxy.GalaxyWallpaper</string>
这里的com.android.wallpaper/com.android.wallpaper.galaxy.GalaxyWallpaper 是动态壁纸的service的名字。
eclipse出现 Some characters cannot be mapped using "GBK" character encoding 错误代码的解决办法
今天在使用eclipse调试腾讯空间API时,在我更改APP key后,点击保存按钮时,出现了Some characters cannot be mapped using "GBK" character encoding 这样的错误代码,根据提示看,应该是说一些文字无法用GBK编码映射。应该是有些地方的文字编码设置成了GBK造成的。
马上google了一番,终于找到了解决的办法,依次点击Window->Profermance->General->Content Type->Text看目录下面的每个文件,包括子目录里面 Default encoding的值是否为utf-8,如果为别的值或为空,则全部改为utf-8,每一项改完,别忘了点一下update.全部改完后推出菜单,再点一下保存,终于成功了。
在Android源码下如何对APK手动签名呢?需要如下几个步骤:
1、编译signapk JAR包:在Android源码目录下执行make signapk命令,即可在out/host/linux-x86/framework/目录下生成signapk.jar文件。
2、对已编译好的普通APK进行签名:
java -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 xinu.apk xinu_new.apk
以上都是在Android源码目录下执行,对xinu.apk进行签名,签名后名为xinu_new.apk,其中pem和pk8是签名时要用到的key文件,使用Android源码下的key可在编译出来系统上运行时获取System权限等。
-----------------------------------------------------
需要先打一个未签名的APK包,然后用系统签名对其进行签名。使用platform密钥对apk进行签名
1.1.进入<Android_Source_Path>/build/target/product/security,找到【platform.pk8】和【platform.x509.pem】系统密钥。
1.2.进入<Android_Source_Path>/build/tools/signapk找到SignApk.java,运行javac编译成SignApk.class
1.3.执行命令java com.android.signapk.SignApk platform.x509.pem platform.pk8 input.apk output.apk
至此,完成。
在运行1.3的命令前,请在你当前的工作目录下新建如下结构的文件夹:com.android.signapk,然后将第二步编译生成的SignApk放入该目录下。或者也可以将SignApk.java的package声明删除后再运行javac编译。
命令java com.android.signapk.SignApk platform.x509.pem platform.pk8 input.apk output.apk
不单可以对apk文件进行重签名,也可以对所有的zip文件进行重签名,包括ROM文件。
以上这方法在AndroidManifest中声明android.permission.INSTALL_PACKAGES,有一点比较奇怪的是执行“ int result = checkCallingOrSelfPermission(Intent.ACTION_PACKAGE_INSTALL) ”,result的值为android.content.pm.PackageManager.PERMISSION_DENIED而不是PERMISSION_GRANTED。
取得某个文件夹下特定格式文件列表
private static final String MUSIC_PATH = new String("/sdcard/"); File file = new File(MUSIC_PATH); File fileArray[] = file.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { // TODO Auto-generated method stub return (filename.endsWith(".mp3")); } }); List<String> mMusicList = new ArrayList<String>(); for(File item: fileArray){ mMusicList.add(item.getName()); }
屏常亮代码:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//屏常亮
自定义组合控件加载layout:
LayoutInflater.from(context).inflate(R.layout.cam_control_bar, this, true);
自定义控件不调用onDraw函数:
android默认不调用onDraw函数,在自定义view里如需手动绘制,需要在构造函数调用this.setWillNotDraw(false);来告诉ui线程此自定义layout有需要绘制的内容
实现序列图切换 就是一张图有几张小图组成 按时间切换 (java实现)
int currImage=0; Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { if (msg.what==0x123) { currImage++; invalidate(); } } }; dukeImage=new Bitmap[]{ BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10001), BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10002), BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10003), BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10004), BitmapFactory.decodeResource(context.getResources(),R.drawable.qt10005), }; new Timer().schedule(new TimerTask(){ @Override public void run() { handler.sendEmptyMessage(0x123); } }, 0,200); } public void onDraw(Canvas canvas) { canvas.drawBitmap(dukeImage[currImage], LEFTMART, screenHeight-ImageHeight-BOTTOM, paint); }
转自:http://www.cnblogs.com/bastard/archive/2012/06/29/2570405.html
/**
*
* 简单实现了一个方法来判断动画的状态。CustomAnimDrawable是自己写的继承于AnimationDrawable的
*
* 一个类,用来根据播放第几帧来判断,避免了根据时间来判断时,理论时间和实际时间不一致造成的影响。
*
* 用到了Java的反射机制。
*
*/
public class CustomAnimDrawable extends AnimationDrawable {
private final String TAG = "xmp";
private AnimationDrawable mOriAnim;
private AnimationDrawable mSelf;
private Handler mHandler;
private boolean mStarted;
private AnimEndListenerRunnable mEndRunnable;
private AnimationDrawableListener mListener;
public CustomAnimDrawable(AnimationDrawable anim) {
mOriAnim = anim;
initialize();
}
private void initialize() {
mSelf = this;
mStarted = false;
mHandler = new Handler();
mEndRunnable = new AnimEndListenerRunnable();
for (int i = 0; i < mOriAnim.getNumberOfFrames(); i++) {
mSelf.addFrame(mOriAnim.getFrame(i), mOriAnim.getDuration(i));
}
}
@Override
public void start() {
mOriAnim.start();
mStarted = true;
mHandler.post(mEndRunnable);
if (mListener != null) {
mListener.onAnimationStart(mSelf);
}
Log.v(TAG, "------CustomAnimDrawable------>start");
}
/**
* 循环检测 动画的状态
*/
class AnimEndListenerRunnable implements Runnable {
@Override
public void run() {
// 动画已开始
if (!mStarted) {
return;
}
// 未停止继续监听
if (!isEnd()) {
// 这里的延迟时间是跟你的每一帧动画时间有关,基本保持一致就可以,最后一帧也会完整播放
// 上面动画时间为每一帧1000ms,所以这里设为了1000ms
mHandler.postDelayed(mEndRunnable,1000);
return;
}
Log.v(TAG, "----------->over");
// 动画已结束
if (mListener != null) {
mStarted = false;
mListener.onAnimationEnd(mSelf);
}
}
}
/**
* 判断动画是否结束 采用反射机制
* @return
*/
private boolean isEnd(){
Class<AnimationDrawable> animClass = AnimationDrawable.class;
try{
//利用Java反射方法判断是否结束
//获得私有方法 例如
//Method method = animClass.getDeclaredMethod("nextFrame",boolean.class);
//访问其私有变量
Field field = animClass.getDeclaredField("mCurFrame");
field.setAccessible(true);
int currFrameNum = field.getInt(mOriAnim);
int totalFrameNum = mOriAnim.getNumberOfFrames();
if((currFrameNum == totalFrameNum - 1)||
(currFrameNum == -1)){
return true;
}
}
catch (Exception e) {
Log.v(TAG,"-------->Exception");
}
return false;
}
public void setAnimationListener(AnimationDrawableListener listener) {
mListener = listener;
}
}
public interface AnimationDrawableListener {
/**
* Notifies the start of the animation
* @param animation
*/
public void onAnimationStart(AnimationDrawable animation);
/**
* Notifies the end of the animation
* @param animation
*/
public void onAnimationEnd(AnimationDrawable animation);
}
TextView相关:
android:imeOptions="actionSearch" 调整输入法enter键的显示
android:inputType="textNoSuggestions" 限制字符(输入格式) InputFilter
android:focusableInTouchMode="true" 获取焦点 <requestFocus />
mSearchEdit.setFocusable(true);
mSearchEdit.setFocusableInTouchMode(true);
mSearchEdit.requestFocus();
如何将TextView中的中文设置成粗体?
在xml文件中使用android:textStyle="bold" 可以将英文设置成粗体,但是不能将中文设置成粗体,将中文设置成粗体的方法是:
TextView tv = (TextView)findViewById(R.id.TextView01);
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(true);
输入法相关:
默认输入法:1、frameworks\base\packages\SettingsProvider\res\values\defaults.xml
<string name="default_enabled_input_methods" translatable="false">com.jb.gokeyboard/.GoKeyboard</string>
2、frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java
函数private void loadSecureSettings(SQLiteDatabase db)() 中 增加语句 loadStringSetting(stmt, Settings.Secure.DEFAULT_INPUT_METHOD, com.android.internal.R.string.default_enabled_input_methods);
4.2.2 pad中使用:
<activity android:windowSoftInputMode="stateHidden|adjustPan" . . . > 调整输入法初始隐藏,并且不调整出口尺寸大小
详见: http://www.cnblogs.com/snowberg/archive/2012/07/10/2618910.html
强制隐藏Android输入法窗口
在IME类中我们通过 InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 实例化输入法控制对象,通过hideSoftInputFromWindow来控制,其中第一个参数绑定的为需要隐藏输入法的EditText对象,比如imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
EditText editText=...
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View arg0, boolean arg1) {
// TODO Auto-generated method stub
if(!arg1){ //失去焦点,关闭输入界面
InputMethodManager imm = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
}
});
SQL中 inner join、 left join 、right join、 outer join之间的区别
举例说明A表(a1,b1,c1) B表(a2,b2)
a1 b1 c1 a2 b2
01 数学 95 01 张三
02 语文 90 02 李四
03 英语 80 04 王五
select A.*,B.* from A
inner join B on(A.a1=B.a2)
结果是:
a1 b1 c1 a2 b2
01 数学 95 01 张三
02 语文 90 02 李四
select A.*,B.* from A
left outer join B on(A.a1=B.a2)
结果是:
a1 b1 c1 a2 b2
01 数学 95 01 张三
02 语文 90 02 李四
03 英语 80 NULL NULL
select A.*,B.* from A
right outer join B on(A.a1=B.a2)
结果是:
a1 b1 c1 a2 b2
01 数学 95 01 张三
02 语文 90 02 李四
NULL NULL NULL 04 王五
select A.*,B.* from A
full outer join B on(A.a1=B.a2)
结果是:
a1 b1 c1 a2 b2
01 数学 95 01 张三
02 语文 90 02 李四
03 英语 80 NULL NULL
NULL NULL NULL 04 王五
如果让包含button的item也能弹出菜单,回调click以及long click的监听器:
设置button属性: android:focusable="false" 另外还要设置
listview属性:android:longClickable="true"
PS: 如果包含的Button是ImageButton,那么在xml中设置了android:focusable="false"属性在当前版本是无效的,必须在代码中,再次呼叫函数ImageButton.setFocusable(false)设置一次。
或者:
在父Item里面加上android:descendantFocusability="blocksDescendants"
背光亮度: /sys/class/leds/lcd-backlight/brightness
例如 echo 255 > /sys/class/leds/lcd-backlight/brightness
代码修改亮度:
Settings.System.putInt(getContentResolver(),
SCREEN_BRIGHTNESS, brightness); //brightness 背光亮度 0~255
Settings.System.putInt(getContentResolver(),SCREEN_OFF_TIMEOUT, timeoutValues);//timeoutValues
灭屏时间 ms
FrameLayout
如何自定义title的高度、背景
Android程序默认的Activity标题栏只能显示一段文字,而且不能改变它的布局、颜色、标题栏的高度等。如果想要在标题栏加上个图标、button、输入框、进度条、修改标题栏颜色等,只能使用自定义的标题栏。自定义标题栏可以通过在onCreate函数中添加以下代码来实现,需要注意的是代码的顺序必须按照下面的样式,否则将无效。
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.mainactivity); //Activity的布局
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.titlebar); //标题栏的布局
虽然上面这样可以在标题栏加入一些控件,但是仍然不能改变标题栏的高度、背景色,要想达到这个目的,只能使用theme(主题)。因此往project里先添加一个style。改变背景色修改android:windowTitleBackgroundStyle的值,改变标题栏高度则修改android:windowTitleSize的值。下面是一个示例:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="fmTitleBackground">
<item name="android:background">#778899</item>
</style>
<style name="fmTitlebar" parent="android:Theme">
<item name="android:windowTitleSize">32dp</item>
<item name="android:windowTitleBackgroundStyle">@style/fmTitleBackground</item>
</style>
</resources>
接着再修改AndroidManifest.xml文件,找到要自定义标题栏的Activity,添加上android:theme值,比如:<activity android:name=".MainActivity" android:theme="@style/fmTitlebar">android:theme值就是上面那个style.xml文件里定义的一个style的name值。
按照以上的步骤,修改标题栏布局、高度、背景色的功能就实现了。
重新显示一个已经启动的Activity呢 不重新启动它 只是让它显示到最前面 : A ->B->C->D 现在想要 从 D直接到B
Intent intent = new Intent(ReorderFour.this, ReorderTwo.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
Android2.1的源代码的目录结构,可以帮助我们研究Android的源代码。
http://www.cnblogs.com/xilinch/archive/2013/04/07/3003670.html
判断是否在锁屏界面的函数
KeyguardManager: inKeyguardRestrictedInputMode();
例: KeyguardManager km = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
boolean keyguardexist = km.inKeyguardRestrictedInputMode();
设置activity背景透明:
1、在AndroidManifest.xml文件中相应的activity下增加属性 android:theme="@android:style/Theme.Translucent"2、先在res/values下建colors.xml文件,写入:
<?xm version="1.0"encoding="UTF-8"?>
<resources>
<color name="transparent">#9000</color>
</resources>
这个值设定了整个界面的透明度,为了看得见效果,现在设为透明度为56%(9/16)左右。
再在res/values/下建styles.xml,设置程序的风格
<?xml version="1.0"encoding="utf-8"?>
<resources>
<style name="Transparent">
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@+android:style/Animation.Translucent</item>
</style>
</resources>
最后一步,把这个styles.xml用在相应的Activity上。即在AndroidManifest.xml中的任意<activity>标签中添加 android:theme="@style/Transparent"
如果想设置所有的activity都使用这个风格,可以把这句标签语句添加在<application>中。
可以把背景色#9000换成#0000,运行程序后,就全透明了,看得见背景下的所有东西可以却都操作无效。
双击事件
private long mLastTime = 0;
private long mCurTime = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
if(MotionEvent.ACTION_DOWN == event.getAction()){
mLastTime = mCurTime;
mCurTime = System.currentTimeMillis();
if (mCurTime - mLastTime < 1000) {
// 双击事件 关闭activity
FullBlackActivity.this.finish();
return true;
}
}
return false;
}
}
屏常亮(camera中的代码)
private void resetScreenOn() {mHandler.removeMessages(CLEAR_SCREEN_DELAY);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private void keepScreenOnAwhile() {
mHandler.removeMessages(CLEAR_SCREEN_DELAY);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
}
private static final int CLEAR_SCREEN_DELAY = 1;
private static final int SCREEN_DELAY = 2 * 60 * 1000;
private final Handler mHandler = new MainHandler();
private class MainHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CLEAR_SCREEN_DELAY: {
getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
break;
}
}
}
}
去除锁屏、开机不锁屏
KeyguardManager mKeyguardManager;
KeyguardManager.KeyguardLock mKeyguardLock;
mKeyguardManager=(KeyguardManager )getSystemService(Context.KEYGUARD_SERVICE);
mKeyguardLock = mKeyguardManager.newKeyguardLock(this.getLocalClassName());
mKeyguardLock.disableKeyguard(); //去除锁屏
mKeyguardLock.reenableKeyguard();//重新使能锁屏
去除开机锁屏的功能:frameworks/base/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
private boolean mExternallyEnabled = false;
或者也可以在函数中frameworks/base/services/java/com/android/server/wm/WindowManagerService.java private void initPolicy(Handler uiHandler) 增加代码达到不锁屏功能
--- frameworks/base/services/java/com/android/server/wm/WindowManagerService.java (revision 337) +++ frameworks/base/services/java/com/android/server/wm/WindowManagerService.java (working copy) @@ -863,6 +863,11 @@ mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET; + + Log.v(TAG, "set mExternallyEnabled true! " ); //jimbo set KeyguardViewMediator.mExternallyEnabled = false + mPolicy.enableKeyguard(false); } }, 0); }
默认锁屏时间: frameworks/base/packages/SettingsProvider/res/values/defaults.xml
<integer name="def_screen_off_timeout">-1</integer> -1 代表不锁屏
默认横屏显示
1、setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // 进入时会先显示一下竖屏然后再横屏
2、在AndroidManifest.xml文件中相应的Activity增加属性 android:screenOrientation="landscape"
取得所有需要显示在主菜单中的程序
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> allApps = getPackageManager().queryIntentActivities(mainIntent, 0);
自动内存管理 --- 内存等级(剩多少内存开始关闭相应应用):
3rdparty\wifi\rda5990\special\android\system\core\rootdir\init.rc里面的
# Define the memory thresholds at which the above process classes will
# be killed. These numbers are in pages (4k).
setprop ro.FOREGROUND_APP_MEM 2048 (限制后台程序内存的)
setprop ro.VISIBLE_APP_MEM 3072
setprop ro.HOME_APP_MEM 3072
setprop ro.PERCEPTIBLE_APP_MEM 4096
setprop ro.HEAVY_WEIGHT_APP_MEM 4096
setprop ro.SECONDARY_SERVER_MEM 15360
setprop ro.BACKUP_APP_MEM 15360
setprop ro.HIDDEN_APP_MEM 15360
setprop ro.EMPTY_APP_MEM 14336
# Write value must be consistent with the above properties.
# Note that the driver only supports 6 slots, so we have combined some of
# the classes into the same memory level; the associated processes of higher
# classes will still be killed first.
write /sys/module/lowmemorykiller/parameters/adj 0,1,2,4,7,15
write /proc/sys/vm/overcommit_memory 1
write /proc/sys/vm/min_free_order_shift 4
write /sys/module/lowmemorykiller/parameters/minfree 2048,3072,4096,15360,15360,14336
参考:http://bbs.hiapk.com/thread-1165395-1-1.html http://bbs.fengbao.com/thread-869501-1-1.html
1.FOREGROUND_APP:前台程序
This is the process running the current foreground app. We‘d really rather not kill it!
用户正在使用的程序. 这个设的太高,用户看到得就会是一个正在使用的程序莫名其妙的消失了,然后自动回到桌面..(因为它被系统kill了..) 所以最好别动它..
目前正在屏幕上显示的进程和一些系统进程。举例来说,Dialer Storage,Google Search等系统进程就是前台进程;再举例来说,当你运行一个程序,如浏览器,当浏览器界面在前台显示时,浏览器属于前台进程(foreground),但一旦你按home回到主界面,浏览器就变成了后台程序(background)。我们最不希望终止的进程就是前台进程
2.. VISIBLE_APP: 可见程序
This is a process only hosting activities that are visible to the user, so we‘d prefer they don‘t disappear.
跟FOREGROUND_APP类似,用户正在使用/看得到. 它们的区别就是VISIBLE_APP可能不是用户预期需要的程序,但是用户看得到. 所以可以适当的比FOREGROUND_APP高一点.
可见进程是一些不再前台,但用户依然可见的进程,举个例来说:widget、输入法等,都属于visible。这部分进程虽然不在前台,但与我们的使用也密切相关,我们也不希望它们被终止(你肯定不希望时钟、天气,新闻等widget被终止,那它们将无法同步,你也不希望输入法被终止,否则你每次输入时都需要重新启动输入法)
3. SECONDARY_SERVER:次要服务
This is a process holding a secondary server -- killing it will not have much of an impact as far as the user is concerned.
所有应用的service. 系统级的service比如PhoneService不属于这类,它们是绝不会被Android结束掉的. 所以这个可以适当的设高一点点~ 注意, HOME(SenseUI)也包括在这里 因此还是别设的太高. 要不每次返回桌面都得等它重新load,特别是widget多的..
目前正在运行的一些服务(主要服务,如拨号等,是不可能被进程管理终止的,故这里只谈次要服务),举例来说:谷歌企业套件,Gmail内部存储,联系人内部存储等。这部分服务虽然属于次要服务,但很一些系统功能依然息息相关,我们时常需要用到它们,所以也太希望他们被终止
4.BACKUP APP MEMORY :(背景数据程序内存)
这个ANDROID系统里是合并到上面的3.次要服务里的,这个应该是后台谷歌同步数据(日历,联系人,地图)
5.HOME-app-memory (桌面程序内存)
这个同样ANDROID是合并到上面的3.次要服务里的,其实应该是桌面LUNCHER类应用程序(ADW LP)
6.HIDDEN_APP:(隐藏程序)
This is a process only hosting activities that are not visible, so it can be killed without any disruption.
本来属于1.前台程序或者2.可见程序 的程序, 在用户按了"back返回键"或者"home房子键"后,程序本身看不到了,但是其实还在运行的程序,它们就属于HIDDEN_APP了. 干掉没什么影响.. 不过要了解并不是所有属于这一类的就应该马上结束掉,像push mail,locale,闹钟,等都属于这一类. 因此还是别设的过高. 真正"应该"一点返回键就退出的程序(真正没用的程序)-空程序在下面.
虽然作者用了hidden这个词,但实际即是后台进程(background),就是我们通常意义上理解的启动后被切换到后台的进程,如浏览器,阅读器等。当程序显示在屏幕上时,他所运行的进程即为前台进程(foreground),一旦我们按home返回主界面(注意是按home,不是按back),程序就驻留在后台,成为后台进程
(background)。后台进程的管理策略有多种:有较为积极的方式,一旦程序到达后台立即终止,这种方式会提高程序的运行速度,但无法加速程序的再次启动;也有较消极的方式,尽可能多的保留后台程序,虽然可能会影响到单个程序的运行速度,但在再次启动已启动的程序时,速度会有所提升。这里就需要用户根据自己的使用习惯找到一个平衡点
7.CONTENT_PROVIDER:(内容/节点供应)
This is a process with a content provider that does not have any clients attached to it. If it did have any clients, its adjustment would be the one for the highest-priority of those processes.
这个也是用处不大,但是还是比下面的EMPTY_APP(空程序)稍微有点用.. 所以高点没关系,(大鱼评论:有时候我开了大程序游戏,返回桌面的时候,我的JORTE 日历桌面插件显示会缩小成一小块,应该就是内容/节点供应达到阀值开始释放内存有关。
没有程序实体,进提供内容供别的程序去用的,比如日历供应节点,邮件供应节点等。在终止进程时,这类程序应该有较高的优先权
8.EMPTY_APP:(空程序)
This is a process without anything currently running in it. Definitely the first to go! This value is initalized in the constructor, careful when refering to this static variable externally.
完全没用,杀了它只有好处没坏处,第一个干它!大鱼评论:基本上大家运行的一些正常的第三方程序按返回退出后都变成了空程序!
有任何东西在内运行的进程,有些程序,比如BTE,在程序退出后,依然会在进程中驻留一个空进程,这个进程里没有任何数据在运行,作用往往是提高该程序下次的启动速度或者记录程序的一些历史信息。这部分进程无疑是应该最先终止的。
OOM-ADJ等级:
(可根据“oom_adj”值的范围来决定进程管理策略,比如可以设定“当内存小于X时,结束“oom_adj”大于Y的进程”)
0代表降低进程的优先级且驻留内存;这意味着它不会被系统终止,一旦它不可访问后,会获得个更高的“oom_adj”
1代表驻留内存;
4代表缓存较多的内存;
15代表尽量缓存内存。
也就是说内存缓存器是按照ADJ从大到小来进行缓存的。
一个经典用例:
ro.FOREGROUND_APP_ADJ=0 前台程序驻留内存(不缓存)
ro.VISIBLE_APP_ADJ=1 可见的程序驻留内存(不缓存)
ro.PERCEPTIBLE_APP_ADJ=2 缓存的RAM多一些
ro.HOME_APP_ADJ=3 桌面程序,缓存的RAM稍多一些
ro.HEAVY_WEIGHT_APP_ADJ=4 缓存的RAM再多一些
ro.SECONDARY_SERVER_ADJ=5 缓存的RAM再再多一些
ro.BACKUP_APP_ADJ=6 缓存的RAM再再再多一些
ro.HIDDEN_APP_MIN_ADJ=7 隐藏的程序,根据程序的类型进行内存管理,最低为缓存的RAM再再再再多一些,最高就是直接缓存内存。
ro.EMPTY_APP_ADJ=15 已经退出的程序,直接缓存内存
VSS – Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS – Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS – Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS – Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
可以使用procrank查看Android系统的各进程的VSS/RSS/PSS/USS的值。
free命令:
totoal(1018216KB)是总内存数量,used(992664KB)表示已经使用的数量, free(25552KB)表示空闲数量。其中,total(1018216KB)=used(992664KB)+free(25552KB)。后面的buffers(9700)表示往磁盘空间里“写”的缓冲区大小,cached表示“读”的数据的缓存,它们属于used的一部分。二者可以快速变为可用内存,使用它们出于改善系统IO性能的目的。当不把二者计入时,系统uesd和free的统计值就是下面的一行(-/+ buffers)因此:uesd:749728=992664-9700-233236,free:25552+9700+233236=268488
最下面的一行表示交换到磁盘空间的内存。
显示当前正在运行的activity
class ShowCurrentActivityThd extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
while(true){
ActivityManager mActivityManager = (ActivityManager) MainActivity.this.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName componentName = mActivityManager.getRunningTasks(1).get(0).topActivity;
String packageName = componentName.getPackageName();
String className = componentName.getClassName();
Log.d("TOP_ACTIVITY","package = " + packageName + ", class = " + className);
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
使用方法: new ShowCurrentActivityThd().start(); 然后就会不停的打印当前activity的包名、类名
获取音乐的内置图片
转自 http://blog.csdn.net/tao_zi7890/article/details/8851512
public class ArtworkUtils {
private static final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
private static final BitmapFactory.Options sBitmapOptions = new BitmapFactory.Options();
public static Bitmap getArtwork(Context context, String title, long song_id, long album_id,
boolean allowdefault) {
if (album_id < 0) {
if (song_id >= 0) {
Bitmap bm = getArtworkFromFile(context, song_id, -1);
if (bm != null) {
return bm;
}
}
if (allowdefault) {
return getDefaultArtwork(context);
}
return null;
}
ContentResolver res = context.getContentResolver();
Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);
if (uri != null) {
InputStream in = null;
try {
in = res.openInputStream(uri);
Bitmap bmp = BitmapFactory.decodeStream(in, null, sBitmapOptions);
if (bmp == null) {
bmp = getDefaultArtwork(context);
}
return bmp;
} catch (FileNotFoundException ex) {
Bitmap bm = getArtworkFromFile(context, song_id, album_id);
if (bm != null) {
if (bm.getConfig() == null) {
bm = bm.copy(Bitmap.Config.RGB_565, false);
if (bm == null && allowdefault) {
return getDefaultArtwork(context);
}
}
} else if (allowdefault) {
bm = getDefaultArtwork(context);
}
return bm;
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
private static Bitmap getArtworkFromFile(Context context, long songid, long albumid) {
Bitmap bm = null;
if (albumid < 0 && songid < 0) {
throw new IllegalArgumentException("Must specify an album or a song id");
}
try {
if (albumid < 0) {
Uri uri = Uri.parse("content://media/external/audio/media/" + songid + "/albumart");
ParcelFileDescriptor pfd = context.getContentResolver()
.openFileDescriptor(uri, "r");
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
bm = BitmapFactory.decodeFileDescriptor(fd);
}
} else {
Uri uri = ContentUris.withAppendedId(sArtworkUri, albumid);
ParcelFileDescriptor pfd = context.getContentResolver()
.openFileDescriptor(uri, "r");
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
bm = BitmapFactory.decodeFileDescriptor(fd);
}
}
} catch (FileNotFoundException ex) {
}
return bm;
}
private static Bitmap getDefaultArtwork(Context context) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.RGB_565;
return BitmapFactory.decodeStream(
context.getResources().openRawResource(R.drawable.music_icon), null,
opts);
}
创建阻塞式模态对话框的方法
转自:http://blog.csdn.net/winux/article/details/6269687 和 http://www.eoeandroid.com/thread-272252-1-1.html
import android.app.Activity;
import android.app.Dialog;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.method.PasswordTransformationMethod;
import android.text.method.TransformationMethod;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
public class PasswordDialog extends Dialog
{
int dialogResult;
Handler mHandler ;
public PasswordDialog(Activity context, String mailName, boolean retry)
{
super(context);
setOwnerActivity(context);
onCreate();
TextView promptLbl = (TextView) findViewById(R.id.promptLbl);
promptLbl.setText("请输入密码/n" + mailName);
}
public int getDialogResult()
{
return dialogResult;
}
public void setDialogResult(int dialogResult)
{
this.dialogResult = dialogResult;
}
/** Called when the activity is first created. */
public void onCreate() {
setContentView(R.layout.password_dialog);
findViewById(R.id.cancelBtn).setOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(View paramView)
{
endDialog(DialogResult.CANCEL);
}
});
findViewById(R.id.okBtn).setOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(View paramView)
{
endDialog(DialogResult.OK);
}
});
}
public void endDialog(int result)
{
dismiss();
setDialogResult(result);
Message m = mHandler.obtainMessage();
mHandler.sendMessage(m);
}
public int showDialog()
{
mHandler = new Handler() {
@Override
public void handleMessage(Message mesg) {
// process incoming messages here
//super.handleMessage(msg);
throw new RuntimeException();
}
};
super.show();
try {
Looper.getMainLooper().loop();
}
catch(RuntimeException e2)
{
}
return dialogResult;
}
}
网络连接相关
转自:http://blog.csdn.net/tao_zi7890/article/details/9278955
/**
* 获取当前的网络状态 -1:没有网络 1:WIFI网络2:wap网络3:net网络
*/
public int getAPNType(Context context){
int CMNET = 3, CMWAP=2, WIFI=1;
int netType = -1;
ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
android.net.NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if(networkInfo==null){
return netType;
}
int nType = networkInfo.getType(); // 取得类型
if(nType==ConnectivityManager.TYPE_MOBILE){
log("networkInfo.getExtraInfo()"+ " networkInfo.getExtraInfo() is "+networkInfo.getExtraInfo());
if(networkInfo.getExtraInfo().toLowerCase().equals("cmnet")){
netType = CMNET;
}
else{
netType = CMWAP;
}
}
else if(nType==ConnectivityManager.TYPE_WIFI){
netType = WIFI;
}
return netType;
}
//判断是否连接到网络
android.net.NetworkInfo[] networkInfo = connectivity.getAllNetworkInfo();
if (networkInfo != null) {
for (int i = 0; i < networkInfo .length; i++) {
if (networkInfo [i].getState() == android.net.NetworkInfo.State.CONNECTED) {
log("netWorkNameis:"+networkInfo [i].getTypeName()+" subTypeName="+inetworkInfo fo[i].getSubtypeName()+" NetWorkState is:"+ "Availabel");
return true;
}
}
}
或者:
android.net.NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null) {
return networkInfo.isAvailable();
}
网络类型:
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); //0
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);//1
TYPE_MOBILE_MMS //2 、 .....TYPE_BLUETOOTH //7
打开/关闭wifi
private void setWifi(boolean on) { // TODO Auto-generated method stub if (mWifiManager == null) { // mWifiManager = (WifiManager)this.getSystemService(Context.WIFI_SERVICE); return; } Log.d("jimbo", "wifi====" + mWifiManager.isWifiEnabled()+ " is going to state:"+on); if (on) {// 开启wifi if (!mWifiManager.isWifiEnabled()) { mWifiManager.setWifiEnabled(true); } } else { // 关闭 wifi if (mWifiManager.isWifiEnabled()) { mWifiManager.setWifiEnabled(false); } } }
打开/关闭蓝牙 bt
private void setBT(boolean enable) { // TODO Auto-generated method stub if (btAdapter == null) { //btadapter = BluetoothAdapter.getDefaultAdapter(); Log.d("jimbo", "not support bluetooth"); } else { if (enable) { btAdapter.enable(); } else { btAdapter.disable(); } IntentFilter intentFilterBt = new IntentFilter(); intentFilterBt.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); intentFilterBt.addAction(BluetoothDevice.ACTION_FOUND); intentFilterBt.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); intentFilterBt.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); intentFilterBt.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(mBtStateReceiver , intentFilterBt); btAdapter.startDiscovery(); } }
Intent的使用
1、显示使用Explicit 当你有一个消息需要传递,如果你明确知道你需要哪个Activity 或者其他Class 来响
应的话,你可以指定这个类来接受该消息,这被称为显性发送。你需要将Intent 的class 属性设置成目标。用setClass或setComponent来设置
Intent的发起方与接收方
2、隐式使用Implicit 不需要用setClass或setComponent来指定事件处理 器,利用AndroidMenifest.xml中的配置由平台定位事件的消费者
intent要定位事件的目的地,无外乎需要以下几个信息:
1).种类(category),比如我们常见的 LAUNCHER_CATEGORY 就是表示这是一类应用程序。
2).类型(type),在前面的例子中没用过,表示数据的类型,这是隐性Intent定位目标的重要依据。
3).组件(component),前面的例子中用的是setClass,不过也可以用setComponent来设置intent跳转的前后两个类实例。
4).附加数据(extras),在ContentURI之外还可以附加一些信息,它是Bundle类型的对象。
举例:
增加一个类:HelloThreeProvider,它必须实现于ConentProvider接口,然后,在AndroidMenifest.xml中我们将上面这个HelloThreeProvider类加入应用程序 <provider class="HelloThreeProvider"
android:authorities="cn.sharetop.android.hello" />
隐式使用 Intent intent = new Intent();
//使用在AndroidMenifest.xml中定义的android:authorities 的标签
content://+authorities+
intent.setData(new ContentURI("content://cn.sharetop.android.hello/one"));
intent.setAction(intent.VIEW_ACTION);
startActivity(intent);
现在我们的setData里的东西可与以前不一样的,是吧?注意到它的格式了吗?content://是个协议头,固定这样写就行了。然后就是那个authorities中定义的串了,再后面就是我们自定义的东西了,我这里很简单的写个one,其它还可以更长一点,如one/101之类的。它负责去关联上那个provider类。另外,增加了setAction的调用设置操作为VIEW_ACTION,与Menifest中的<action>又挂上了。Android平台负责根据Intent的Data信息中的authorities,找到ContentProvider,然后getType,用type和intent中的Action两个信息,再找到可以处理这个intent的消费者。
转自:http://www.sf.org.cn/Android/lumen/20979.html
判断Bitmap 是否是.9图片
//private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) { // BitmapFactory.java
byte[] np = bm.getNinePatchChunk();
final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
拍照并保存到SD卡代码:
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, SystemCapture);
{
if(m_camera != null)
m_camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
public void open()
{
if(m_camera == null)
m_camera = Camera.open();
}
public void release()
{
if(m_camera != null)
{
m_camera.release();
m_camera = null;
}
}
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter‘d");
}
};
/** Handles data for raw picture */
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
/** Handles data for jpeg picture */
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
try
{
Bitmap bitmapPicture = BitmapFactory.decodeByteArray(data, 0, data.length);
String path = Environment.getExternalStorageDirectory().toString();
String filename;
Date date = new Date(0);
SimpleDateFormat sdf = new SimpleDateFormat ("yyyyMMddHHmmss");
filename = sdf.format(date);
OutputStream fOut = null;
//File file = new File(path, "/DCIM/"+filename+".jpg");
File file = new File(path, "/"+filename+".jpg");
fOut = new FileOutputStream(file);
//FileOutputStream out = new FileOutputStream(String.format("/sdcard/DCIM/Signatures/%d.jpg", System.currentTimeMillis()));
bitmapPicture.compress(Bitmap.CompressFormat.JPEG, 0, fOut);
fOut.flush();
fOut.close();
MediaStore.Images.Media.insertImage(m_contentResolver,file.getAbsolutePath(),file.getName(),file.getName());
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
camera.startPreview();
}
Log.d(TAG, "onPictureTaken - jpeg");
}
};
实现录像功能
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, SystemVideoRecord);
取得前、后摄像头
private int getFrontCameraId(){
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); // get cameras number
if(cameraCount == 0){
mCameraId = -1 ;
Toast.makeText(this, "no camera devices avalible! finish this acitivty", Toast.LENGTH_LONG).show();
finish();
}else if(cameraCount == 1) {
mCameraId = 0;
}else{
for(int camIdx = 0; camIdx < cameraCount; camIdx++ ) {
Camera.getCameraInfo(camIdx, cameraInfo ); // get camerainfo
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT ) {
// 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
mCameraId = camIdx;
break;
}
}
}
return mCameraId;
}
回到待机界面
Intent home = new Intent(Intent.ACTION_MAIN);home.addCategory(Intent.CATEGORY_HOME);
this.startActivity(home);
锁屏可以根据GSensor旋转
public static boolean shouldEnableScreenRotation(Context context) { ///M: when is alarm boot,disable rotation @{ if (PowerOffAlarmManager.isAlarmBoot()) { return false; } ///@} return SystemProperties.getBoolean("lockscreen.rot_override",false) || context.getResources().getBoolean(R.bool.config_enableLockScreenRotation); }
所以可以i修改
lockscreen.rot_override=true都可以实现锁屏界面的旋转
</pre></div><h3>设置(Settings)<span style="background-color:#ff9632">默认</span>值</h3><p>frameworks/base/packages/SettingsProvider/src/com/Android/providers/settings/DatabaseHelper.java</p><p>loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT, R.integer.def_screen_off_timeout);</p><p>R.integer.def_screen_off_timeout来初始化。我们为了让系统永不锁屏,只需要把资源 R.integer.def_screen_off_timeout设为-1即可。查看文件</p><p>frameworks\base\packages\SettingsProvider\res\values\defaults.xml 设置里面的<span style="background-color:#ffd700">默认</span>值 例:def_screen_off_timeout <span style="background-color:#ffd700">默认</span>锁屏时间frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java 函数loadSystemSettings(SQLiteDatabase db) 加载各个<span style="background-color:#ffd700">默认</span>值SoundSettings.java mDtmfToneDefaultValue<span style="background-color:#ffd700">默认</span>按键音</p><p>开机<span style="background-color:#ffd700">默认</span>锁屏 :</p><p>frameworks/policies/base/phone/com/Android/internal/policy/impl/KeyguardViewMediator.java该文件中有一个变量定义如下: /** * External apps (like the phone app) can tell us to disable the keygaurd. */ private boolean mExternallyEnabled = true;mExternallyEnabled是用来管理是否开启屏幕锁的关键。<span style="background-color:#ffd700">默认</span>值是打开屏锁 </p><p>默认时间格式: </p><p>DateFormat.java is24HourFormat()</p><p>android源码是根据地区自适应选择是24小时还是12小时</p><p>代码:</p><pre code_snippet_id="76283" snippet_file_name="blog_20131121_3_7535774" class="java" name="code"> if (value == null) { Locale locale = context.getResources().getConfiguration().locale; …… java.text.DateFormat natural = java.text.DateFormat.getTimeInstance( java.text.DateFormat.LONG, locale); ……
}
如果要去掉自适应,可以修改
java.text.DateFormat.LONG, locale); ->java.text.DateFormat.LONG, Locale.UK); //24小时格式
java.text.DateFormat.LONG, locale); ->java.text.DateFormat.LONG, Locale.US.); //12小时格式
修改默认时间
mtk中默认时间设置:
\alps\mediatek\custom\[project]\preloader\ inc\cust_rtc.h
\alps\mediatek\custom\[project]\kernel\rtc\rtc\rtc-mt65XX.h
#define RTC_DEFAULT_YEA 2010
#define RTC_DEFAULT_MTH 1
#define RTC_DEFAULT_DOM 1
也可以在kernel中使用代码设置时间
(在android中,Linux内核中、rtc时钟,默认的起始日期都是1970年1月1日,那么如何把默认日期指到2012-01-01呢?笔者在实践中发现,在RTC驱动中可以很容易实现。在RTC驱动加载的时候,一般都有个probe函数需要先执行,因此在probe函数里下手最直接有效。RTC从1970-01-01开始,那当然很容易把默认值设置到2012-01-01,所需要设置的seconds也就是从1970-01-01所差的秒数,以秒为单位。因此,一旦读出来的RTC值小于我们预想的值比如2012-01-01(1325402913)小,我们就把它设置到这个时间点。)
seconds = rtc_read_time(); printk("init PMU/RTC time to %ld \n", seconds); if(seconds <= 1325402913) { seconds = 1325402913;/*2012-01-01*/ ret = rtc_set_time(seconds); RTC_DBG("Init Set time: %ld, ret =0x%x\n", seconds, ret); }
java 24小时格式显示转换
在使用SimpleDateFormat时格式化时间的 yyyy.MM.dd 为年月日而如果希望格式化时间为12小时制的,则使用hh:mm:ss 如果希望格式化时间为24小时制的,则使用HH:mm:ss
Date d = new Date(); SimpleDateFormat ss = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//12小时制 System.out.println(ss.format(d)); Date date = new Date(); SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//24小时制 String LgTime = sdformat.format(date); System.out.println(LgTime);
xml 字符串中特殊字符& 、<、>、 ‘、" 的处理
& 使用& 代替 ‘ 使用\‘ 代替‘
> > 大于号
& & 和
' ‘ 单引号
" " 双引号
<i></i> 斜体字体
<u></u> 给字体加下划线
\n 换行
\u0020表示空格
\u2026表示省略号
使用<b>和<b>来打印出<b></b> 这样的文字;“<”表示“<”的意思;
使用textView.setText(Html.fromHtml("Hello <b>World</b>,<font size=\"3\" color=\"red\">AnalysisXmlActivty!</font>"));设置类似于html那样的效果
如果你需要使用 String.format(String, Object...) 来格式化你的字符串,你可以把格式化参数放在你的字符串中,参见下面的例子:
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
在这个例子中,这个格式化的字符串有2个参数, %1$s是个字符串 %2$d 是个浮点数,你可以在你的程序中按照下面的方法来根据参数来格式化字符串:
Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
那么根据例子上说的我需要把%s换成%1$s才行了,修改后编译通过,程序成功启动。
问题补充:如何在<string></string>中使用%号
有两个办法可供选择
1.用%%来表示1个%,和转意符号 \ 的用法相同
2.如果你的字符串不需要格式化,可以在你的<string 标签上增加一个属性:formatted="false"例如 <string name="test" formatted="false">% test %</string> 即可
开机后特定的时间内自动发送短信
StartCromeSendMsgReceiver.java
public class StartCromeSendMsgReceiver extends BroadcastReceiver {
private TelephonyManager mTelephonyManager;
private Context mContext = null;
private String mImeiStr = null;
private static final int SEND_SMS_MESSAGE_WHAT = 0x100;
private final Timer mSendSmsTimer = new Timer();
private TimerTask mSendSmsTask = null;
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
mContext = arg0;
if(arg1.getAction().equals( Intent.ACTION_BOOT_COMPLETED )) {
//延时时间 1小时start
mSendSmsTask = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
if(!isSendSmsFlagExist()){
Message message = mSendSmsHandler.obtainMessage();
message.what = SEND_SMS_MESSAGE_WHAT;
mSendSmsHandler.sendMessage(message);
}
}
};
// start timer
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
long delayTimer = 60*1000; //60*60*1000; //延时时间 1小时
mSendSmsTimer.schedule(mSendSmsTask, delayTimer, delayTimer);
}
}).start();
//延时时间 1小时end
//获取IMEI 号 start
StringBuffer imeiBuffer = new StringBuffer();
int phoneCnt = TelephonyManager.getPhoneCount();
for (int i = 0; i < phoneCnt; i++) {
if(phoneCnt<2)
{
imeiBuffer.append("IMEI:");
}
else
{
imeiBuffer.append("IMEI");
imeiBuffer.append((i + 1));
imeiBuffer.append(":");
}
imeiBuffer.append(((TelephonyManager) arg0.getSystemService(PhoneFactory
.getServiceName(Context.TELEPHONY_SERVICE, i))).getDeviceId());
if(i < (phoneCnt-1))
{
imeiBuffer.append("-");
}
}
mImeiStr = imeiBuffer.toString();
Log.d("StartCromeSendMsgReceiver", "+++++zhangyong[imeiStr]++++++ " + mImeiStr);
//获取IMEI 号 end
}
else if (SEND_SMS.equals(arg1.getAction())) {
log(SEND_SMS);
//createSendSmsFlag();
}else if(DELIVERY_SMS.equals(arg1.getAction())) {
log(DELIVERY_SMS);
if(createSendSmsFlag()){
mSendSmsTimer.cancel();
}
}
}
private void log(String msg) {
// TODO Auto-generated method stub
Log.d("StartCromeSendMsgReceiver", "--"+msg+"--");
}
private Handler mSendSmsHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
// send sms
switch (msg.what) {
case SEND_SMS_MESSAGE_WHAT:
sendImeiSms();
break;
default:
break;
}
}
};
private static final String DELIVERY_SMS = "delivery_sms_ok";
private static final String SEND_SMS = "send_sms_ok";
private static final String SEND_SMS_KEY = "has_send_sms";
private boolean createSendSmsFlag(){
boolean ret = false;
SharedPreferences preferences = mContext.getSharedPreferences("SEND_SMS_FLAG", Context.MODE_PRIVATE);
Editor editor = preferences.edit();
editor.putBoolean(SEND_SMS_KEY, true);
ret = editor.commit();
return ret;
}
private boolean isSendSmsFlagExist(){
boolean ret = false;
SharedPreferences preferences = mContext.getSharedPreferences("SEND_SMS_FLAG",Context.MODE_PRIVATE);
ret = preferences.getBoolean(SEND_SMS_KEY, false);
if(ret){
mSendSmsTimer.cancel();
}
return ret;
}
private void sendImeiSms(){
if(isSendSmsFlagExist()){
return;
}
//String sendingTextString = "测试文本!";
SmsManager sm = SmsManager.getDefault();
PendingIntent sendIntent = PendingIntent.getBroadcast(
mContext, 0,
new Intent(SEND_SMS),0);
PendingIntent deliveryIntent = PendingIntent.getBroadcast(
mContext, 0,
new Intent(DELIVERY_SMS),0);
// new Intent(this, FullBlackActivity.class),0);
// 如果短信没有超过限制长度,则返回一个长度的List。
List<String> texts = sm.divideMessage(mImeiStr);
for (String text : texts) {
//sms.sendTextMessage(“这里是接收者电话号码”, “这里是发送者电话号码”, “这里是短信内容”, null, null);
sm.sendTextMessage("15988888888", "", text, null, deliveryIntent);
//log(text);
}
}
}
然后在 AndroidManifest.xml文件中 增加
<receiver android:name=".StartCromeSendMsgReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="send_sms_ok"/>
<action android:name="delivery_sms_ok"/>
</intent-filter>
</receiver>
拨号:
直接在adb中 拨号: am start -a android.intent.action.CALL -d tel:10086
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "112"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
定时器相关
一、采用Handler与线程的sleep(long)方法
二、采用Handler的postDelayed(Runnable, long)方法
三、采用Handler与timer及TimerTask结合的方法
四、闹钟定时
下面逐一介绍:
一、采用Handle与线程的sleep(long)方法
Handler主要用来处理接受到的消息。这只是最主要的方法,当然Handler里还有其他的方法供实现,有兴趣的可以去查API,这里不过多解释。
1. 定义一个Handler类,用于处理接受到的Message。
Handler handler = new Handler() {
public void handleMessage(Message msg) {
// 要做的事情
super.handleMessage(msg);
}
};
2. 新建一个实现Runnable接口的线程类,如下:
public class MyThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(10000);// 线程暂停10秒,单位毫秒
Message message = new Message();
message.what = 1;
handler.sendMessage(message);// 发送消息
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
3. 在需要启动线程的地方加入下面语句:
new Thread(new MyThread()).start();
4. 启动线程后,线程每10s发送一次消息。
二、采用Handler的postDelayed(Runnable, long)方法
这个实现比较简单一些。
1. 定义一个Handler类
Handler handler=new Handler();
Runnable runnable=new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//要做的事情
handler.postDelayed(this, 2000);
}
};
2. 启动计时器
handler.postDelayed(runnable, 2000);//每两秒执行一次runnable.
3. 停止计时器
handler.removeCallbacks(runnable);
三、采用Handler与timer及TimerTask结合的方法
1. 定义定时器、定时器任务及Handler句柄
private final Timer timer = new Timer();
private TimerTask task;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
// 要做的事情
super.handleMessage(msg);
}
};
2. 初始化计时器任务
task = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
3. 启动定时器
timer.schedule(task, 2000, 2000);
简要说一下上面三步提到的一些内容:
1. 定时器任务(TimerTask)顾名思义,就是说当定时器到达指定的时间时要做的工作,这里是想Handler发送一个消息,由Handler类进行处理。
2. java.util.Timer.schedule(TimerTask task, long delay):这个方法是说,dalay/1000秒后执行task.只执行一次。
java.util.Timer.schedule(TimerTask task, long delay, long period):这个方法是说,delay/1000秒后执行task,然后进过period/1000秒再次执行task,这个用于循环任务,执行无数次,当然,你可以用timer.cancel();取消计时器的执行。
四、闹钟定时
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(SEND_SMS_BEGIN), 0);
am.set(AlarmManager.RTC_WAKEUP, 60*1000, pendingIntent);
android.mk 编译选项
耳机状态
private static final String HEADSET_STATE_PATH = "/sys/class/switch/h2w/state"; 保存状态文件位置
private boolean isHeadsetExists(){ //判断耳机是否插入的函数 FM源码 FMplayService.java
char[] buffer = new char[1024];
int newState = 0;
try {
FileReader file = new FileReader(HEADSET_STATE_PATH);
int len = file.read(buffer, 0, 1024);
newState = Integer.valueOf((new String(buffer, 0, len)).trim());
} catch (FileNotFoundException e) {
Log.e(LOGTAG, "This kernel does not have wired headset support");
} catch (Exception e) {
Log.e(LOGTAG, "" , e);
}
return newState != 0;
}
未插入耳机:
# cat /sys/class/switch/h2w/state
cat /sys/class/switch/h2w/state
0
插入耳机:
# cat /sys/class/switch/h2w/state
cat /sys/class/switch/h2w/state
1
sd卡和sim卡状态判断
//sdcard是否可读写
public boolean IsCanUseSdCard() {try {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
//sim卡是否可读
public boolean isCanUseSim() {try {
TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
return TelephonyManager.SIM_STATE_READY == mgr.getSimState();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
开机启动,检查sim卡是否发生变更
(1)注册receiver,设置意图过滤器<receiver android:name=".receiver.BootCompleteReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
(2)接受开机广播,并判断sim卡时候发生更改
public class BootCompleteReceiver extends BroadcastReceiver {
private static final String TAG = "BootCompleteReceiver";
private SharedPreferences sp;
private TelephonyManager tm;
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG,"手机重启了");
sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
boolean protecting = sp.getBoolean("protecting", false);
//如果防盗保护开启
if(protecting){
//判断sim卡是否发生了变化
tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String currentSim = tm.getSimSerialNumber();
String savedSim= sp.getString("sim", "");
if(savedSim.equals(currentSim)){
// sim卡为发生变化, do nothint
}else{
//sim卡发生了变化
//发送报警短信 给安全号码
SmsManager smsManager = SmsManager.getDefault();
String destinationAddretss = sp.getString("safenumber", "");
smsManager.sendTextMessage(destinationAddretss, null, "sim change !!!", null, null);
}
}
}
}
判断SIM卡属于哪个移动运营商
第一种方法:获取手机的IMSI码,并判断是中国移动\中国联通\中国电信
TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
/** 获取SIM卡的IMSI码
* SIM卡唯一标识:IMSI 国际移动用户识别码(IMSI:International Mobile Subscriber Identification Number)是区别移动用户的标志,
* 储存在SIM卡中,可用于区别移动用户的有效信息。IMSI由MCC、MNC、MSIN组成,其中MCC为移动国家号码,由3位数字组成,
* 唯一地识别移动客户所属的国家,我国为460;MNC为网络id,由2位数字组成,
* 用于识别移动客户所归属的移动网络,中国移动为00,中国联通为01,中国电信为03;MSIN为移动客户识别码,采用等长11位数字构成。
* 唯一地识别国内GSM移动通信网中移动客户。所以要区分是移动还是联通,只需取得SIM卡中的MNC字段即可
*/
String imsi = telManager.getSubscriberId();
if(imsi!=null){
if(imsi.startsWith("46000") || imsi.startsWith("46002")){
//因为移动网络编号46000下的IMSI已经用完,所以虚拟了一个46002编号,134/159号段使用了此编号
//中国移动
}else if(imsi.startsWith("46001")){
//中国联通
}else if(imsi.startsWith("46003")){
//中国电信
}
}
第二种方法
TelephonyManager telManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String operator = telManager.getSimOperator();
if(operator!=null){
if(operator.equals("46000") || operator.equals("46002")){
//中国移动
}else if(operator.equals("46001")){
//中国联通
}else if(operator.equals("46003")){
//中国电信
}
}
在文件 AndroidManifest.xml中添加权限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
取得sim卡的网络类型
public String getNetworkTypeName() {
switch (getNetworkType()) {
case NETWORK_TYPE_GPRS:
return "GPRS";
case NETWORK_TYPE_EDGE:
return "EDGE";
case NETWORK_TYPE_UMTS:
return "UMTS";
case NETWORK_TYPE_HSDPA:
return "HSDPA";
case NETWORK_TYPE_HSUPA:
return "HSUPA";
case NETWORK_TYPE_HSPA:
return "HSPA";
case NETWORK_TYPE_CDMA:
return "CDMA";
case NETWORK_TYPE_EVDO_0:
return "CDMA - EvDo rev. 0";
case NETWORK_TYPE_EVDO_A:
return "CDMA - EvDo rev. A";
case NETWORK_TYPE_EVDO_B:
return "CDMA - EvDo rev. B";
case NETWORK_TYPE_1xRTT:
return "CDMA - 1xRTT";
default:
return "UNKNOWN";
}
}
手机卡种类:
private String getSimType() {
// 获得SIMType
String simType = "";
// 获得系统服务,从而取得sim数据
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
int type = tm.getNetworkType();
System.out.println(Contants.DEBUG+" NetWorkType:"+type);
//Test1:联通USIM卡,在这儿取出来的值为10-------NETWORK_TYPE_HSPA
//Test2:中国移动 神州行OTA 2-----NETWORK_TYPE_EDGE
//Test3:中国移动 动感地带OTA 2-----NETWORK_TYPE_EDGE
//...
switch (type) {
case TelephonyManager.NETWORK_TYPE_UNKNOWN://0
simType= "UNKOWN";
break;
case TelephonyManager.NETWORK_TYPE_GPRS://1
simType= "SIM";
break;
case TelephonyManager.NETWORK_TYPE_EDGE://2
simType= "SIM";
break;
case TelephonyManager.NETWORK_TYPE_UMTS://3
simType= "USIM";
break;
case TelephonyManager.NETWORK_TYPE_CDMA://4
simType= "Either IS95A or IS95B Card";
break;
case TelephonyManager.NETWORK_TYPE_EVDO_0://5
simType= "EVDO revision 0 Card";
break;
case TelephonyManager.NETWORK_TYPE_EVDO_A://6
simType= "EVDO revision A Card";
break;
case TelephonyManager.NETWORK_TYPE_1xRTT://7
simType= "1xRTT Card";
break;
case TelephonyManager.NETWORK_TYPE_HSDPA://8
simType= "HSDPA Card";
break;
case TelephonyManager.NETWORK_TYPE_HSUPA://9
simType= "HSUPA Card";
break;
case TelephonyManager.NETWORK_TYPE_HSPA://10
simType= "USIM";
break;
}
System.out.println(Contants.DEBUG+" sim type :"+simType);
return simType;
}
各种手机卡知识:http://bbs.csdn.net/topics/390199890
单态模式实例
private static Singleton instance = new Singleton(); //这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
二:public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {//注意一定要加上关键字 synchronized 否则有可能得到多个Singleton实例
if (instance==null){
instance=new Singleton();
}
return instance;
}
}
修改 特殊字符的命令(工程命令,如展讯*#*#83789#*#*)
SpecialCharSequenceMgr.java ->handleChars ->handleSecretCode
/**
* Handles secret codes to launch arbitrary activities in the form of *#*#<code>#*#*.
* If a secret code is encountered an Intent is started with the android_secret_code://<code>
* URI.
*
* @param context the context to use
* @param input the text to check for a secret code in
* @return true if a secret code was encountered
*/
static boolean handleSecretCode(Context context, String input) {
// Secret codes are in the form *#*#<code>#*#*
int len = input.length();
if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {
Intent intent = new Intent(Intents.SECRET_CODE_ACTION,
Uri.parse("android_secret_code://" + input.substring(4, len - 4)));
context.sendBroadcast(intent);
return true;
}
return false;
}
makefile详解
http://blog.csdn.net/zirconsdu/article/details/8005415
默认字体大小
frameworks/base/core/java/android/content/res/Configuration.java里面,有个fontScale=1
screen 默认拉伸大小
settings->screen->Screen Scale
默认大小: DEFALUT_SCREEN_SCALE 手机存放路径: /sys/class/graphics/fb0/scale 或 /sys/class/graphics/fb2/scale
ScreenScaleManager.cpp
#define MAIN_DISPLAY_SCALE_FILE "/sys/class/graphics/fb0/scale"
#define AUX_DISPLAY_SCALE_FILE "/sys/class/graphics/fb2/scale"
获得圆角图片的方法
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; }
网络下载
private Runnable mdownApkRunnable = new Runnable() { @Override public void run() { try { URL url = new URL(apkUrl); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.connect(); int length = conn.getContentLength(); InputStream is = conn.getInputStream(); File file = new File(savePath); if(!file.exists()){ file.mkdir(); } String apkFile = saveFileName; File ApkFile = new File(apkFile); FileOutputStream fos = new FileOutputStream(ApkFile); int count = 0; byte buf[] = new byte[1024]; do{ int numread = is.read(buf); count += numread; progress =(int)(((float)count / length) * 100); //更新进度 mHandler.sendEmptyMessage(DOWN_UPDATE); if(numread <= 0){ //下载完成通知<span style="BACKGROUND-COLOR: #ffd700">安装</span> mHandler.sendEmptyMessage(DOWN_OVER); break; } fos.write(buf,0,numread); }while(!interceptFlag);//点击取消就停止下载. fos.close(); is.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch(IOException e){ e.printStackTrace(); } } }; /** * 下载apk * @param url */ private void downloadApk(){ downLoadThread = new Thread(mdownApkRunnable); downLoadThread.start(); }
一个弹出AlertDialog实例、机器重启(reboot)实例
new AlertDialog.Builder(EthernetStaticIP.this) <span style="WHITE-SPACE: pre"> </span>.setTitle(R.string.str_about) <span style="WHITE-SPACE: pre"> </span>.setMessage(R.string.str_reboot) <span style="WHITE-SPACE: pre"> </span>.setPositiveButton(R.string.str_ok, <span style="WHITE-SPACE: pre"> </span> new DialogInterface.OnClickListener() <span style="WHITE-SPACE: pre"> </span> { <span style="WHITE-SPACE: pre"> </span> public void onClick(DialogInterface dialoginterfacd,int i) <span style="WHITE-SPACE: pre"> </span> { <span style="WHITE-SPACE: pre"> </span> <span style="WHITE-SPACE: pre"> </span>//reboot <span style="WHITE-SPACE: pre"> </span> /*final static */String SYSTEMUI_REBOOT_ACTION = "com.android.systemui.reboot"; Intent intent = new Intent(); intent.setAction(SYSTEMUI_REBOOT_ACTION); EthernetStaticIP.this.sendBroadcast(intent); <span style="WHITE-SPACE: pre"> </span> } <span style="WHITE-SPACE: pre"> </span> } <span style="WHITE-SPACE: pre"> </span>) <span style="WHITE-SPACE: pre"> </span>.setNegativeButton(R.string.str_cancel, <span style="WHITE-SPACE: pre"> </span> new DialogInterface.OnClickListener() <span style="WHITE-SPACE: pre"> </span> { <span style="WHITE-SPACE: pre"> </span>public void onClick(DialogInterface dialoginterfacd,int i) <span style="WHITE-SPACE: pre"> </span>{ <span style="WHITE-SPACE: pre"> </span>finish(); <span style="WHITE-SPACE: pre"> </span>} <span style="WHITE-SPACE: pre"> </span> } <span style="WHITE-SPACE: pre"> </span> <span style="WHITE-SPACE: pre"> </span>) <span style="WHITE-SPACE: pre"> </span>.show();reboot代码:
frameworks\base\services\java\com\android\server\wm\WindowManagerService.java 增加代码
final static String SYSTEMUI_POWEROFF_ACTION = "com.android.systemui.poweroff"; final static String SYSTEMUI_REBOOT_ACTION = "com.android.systemui.reboot"; final BroadcastReceiver mAdditionalReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if(SYSTEMUI_POWEROFF_ACTION.equals(intent.getAction())){ Log.d(TAG,"wms calling shutdown dlg from broadcast.."); shutdown();//ShutdownThread.shutdown(context,true); }else if(SYSTEMUI_REBOOT_ACTION.equals(intent.getAction())){ Log.d(TAG,"wms calling shutdown dlg from broadcast.."); reboot(); } } }; public void shutdown() { ShutdownThread.shutdown(mContext, true); } public void reboot() { ShutdownThread.reboot(mContext, null, false); }及注册广播接收
IntentFilter f = new IntentFilter(); f.addAction(SYSTEMUI_POWEROFF_ACTION); f.addAction(SYSTEMUI_REBOOT_ACTION); mContext.registerReceiver(mAdditionalReceiver, f);
获得内存信息,cpu信息、频率等
通过读取文件/proc/cpuinfo系统CPU的类型等多种信息。读取/proc/stat 所有CPU活动的信息来计算CPU使用率 , "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" 存储最大频率的文件的路径, cpuinfo_min_freq最低频率,scaling_cur_freq当前频率
通过读取文件/proc/meminfo的信息获取Memory的总量。
ActivityManager. getMemoryInfo(ActivityManager.MemoryInfo)获取当前的可用Memory量
LOCAL_REQUIRED_MODULES
mms Android.mk 中 含有:LOCAL_REQUIRED_MODULES := SoundRecorder
LOCAL_REQUIRED_MODULES的作用当编译整个android源码时,如果mms模块在编译路径中(即可以编译打包到system.img下),
则会自动编译SoundRecorder,并且打包到system.img,如果不是编译整个源码,只是mm。则不会编译SoundRecorderl生成相应的apk文件。
<xliff:g>标签介绍
定义可变的字符串:
当一个字符串中只包含一个可变的数
例如这样: <string name="tedst"> %d首歌曲。</string>这样正确的
当一个字符串中只包含多个可变的数
例如: <string name="tedst">%d张专辑 %d首歌曲。</string>,这样是错误的
当你字符串中包含多个 %d,需要用xliff:g来格式化字符串
<string name="appwidget_text_format"><xliff:g id="prefix">%1$s</xliff:g>: <xliff:g id="time">%2$s</xliff:g></string>
这个主要用于程序中,动态的插入内容时候使用,例如,
<string name="time">当前时间:<xliff:g id="prefix">%1$s</xliff:g>时 <xliff:g id="time">%2$s</xliff:g>分</string>
然后通过程序,context.getString(R.string.time,"10","05");
将会输出——当前时间:10时05分
属性id可以随便命名
属性example表示举例说明,可以省略
%n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空格
%n$md:代表输出的是整数,n代表是第几个参数,设置m的值可以在输出之前放置空格,也可以设为0m,在输出之前放置m个0
%n$mf:代表输出的是浮点数,n代表是第几个参数,设置m的值可以控制小数位数,如m=2.2时,输出格式为00.00
注意:一定要增加命名空间 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 否则会编译不过Error parsing XML: unbound prefix
android kernel log图片 生成工具
log_make.sh logo_linux_clut224.ppm
#!/bin/sh echo "make logo_linux_clut224.ppm start" cd ./1/ echo "--make linuxlogo.pnm" pngtopnm ../linuxlogo.png > linuxlogo.pnm echo "--make linuxlogo224.pnm" pnmquant 224 linuxlogo.pnm > linuxlogo224.pnm echo "--make logo_linux_clut224.pnm" pnmtoplainpnm linuxlogo224.pnm > logo_linux_clut224.ppm cd .. echo "make logo_linux_clut224.ppm end"
android定位代码
定位出现问题的代码:
12-26 14:29:47.801 I/DEBUG ( 100): backtrace:
12-26 14:29:47.801 I/DEBUG ( 100): #00 pc 00016ce0 /system/lib/libc.so (strcmp+32)
12-26 14:29:47.801 I/DEBUG ( 100): #01 pc 000035bb /system/bin/vold
12-26 14:29:47.801 I/DEBUG ( 100): #02 pc 00003521 /system/bin/vold
12-26 14:29:47.801 I/DEBUG ( 100): #03 pc 00002b57 /system/lib/libsysutils.so (NetlinkListener::onDataAvailable(SocketClient*)+166)
12-26 14:29:47.801 I/DEBUG ( 100): #04 pc 000025cf /system/lib/libsysutils.so (SocketListener::runListener()+490)
在工程的根目录下的shell端输入:addr2line -e out/target/product/rk31sdk/symbols/system/bin/vold 00003521
其中,00003521为出现问题的pc指针
结果为:system/vold/MiscManager.cpp:85
addr2line -e out/target/product/rk31sdk/symbols/system/bin/vold 000035bb
system/vold/G3Dev.cpp:63
android ril的加载
在init.rc文件中进行加载Android RIL模块
service ril-daemon /system/bin/rild -l /system/lib/libreference-ril.so -- -d /dev/ttyS0
也可以手动加载:
/system/bin/rild -l /system/lib/libreference-ril.so -- -d /dev/ttyS0
这两种方式,都将启动rild守护进程,然后通过-l参数将libreference-ril.so共享库链入,libreference-ril.so的参数-d是指加载一个串口设备,/dev/ttyS0则是这个串口设备的具体设备文件,除了参数-d外,还有-s代表加载类型为socket的设备,-p代表回环接口
监控电话状态: 来电、通话中、空闲
获取电话服务: 在启动Activity时间获取电话服务
TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener(); // 手动注册对PhoneStateListener中的listen_call_state状态进行监听通話 telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);MyPhoneStateListener类
/**
* 继承PhoneStateListener类,我们可以重新其内部的各种监听方法
* 然后通过手机状态改变时,系统自动触发这些方法来实现我们想要的功能
*/
public class MyPhoneStateListener extends PhoneStateListener { /** * @param state 通話狀態 * @param incomingNumber 手機號碼 */ @Override public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_IDLE: Log.e("---------", "挂掉"); break; case TelephonyManager.CALL_STATE_RINGING: Log.e("---------", "有来电,号码是:" + incomingNumber); break; case TelephonyManager.CALL_STATE_OFFHOOK: Log.e("---------", "通話中"); default: break; } super.onCallStateChanged(state, incomingNumber); } }
相关权限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
NetworkOnMainThreadException错误解决:在主线程中访问了网络数据
E/AndroidRuntime(1562): android.os.NetworkOnMainThreadException
E/AndroidRuntime(1562): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)
查看Ubuntu版本、位数
1.cat /etc/issue
2.cat /etc/lsb-release
3.uname -a
位数:getconf LONG_BIT
java工具 javah和javap的使用(获取、生成java native函数signature工具)
javap的使用:获得java文件的native函数签名 在工程目录\bin\classes目录下执行 javap -s packagename.classname
例: D:\workspace\TtyTester\bin\classes>javap -s com.odm.tty.ttyutil
Compiled from "TtyUtil.java"
public class com.odm.tty.TtyUtil extends java.lang.Object{
public static final java.lang.String A4_RFID_RDM_TTY_DEV;
。。。
Signature: Ljava/lang/String;
public static final java.lang.String UE966_TTY_DEV;
Signature: Ljava/lang/String;
public com.odm.tty.TtyUtil();
Signature: ()V
}
ubuntu samba可视化共享
sudo apt-get install samba
sudo apt-get install smbfs
sudo apt-get install system-config-samba
sudo /etc/init.d/samba start
sudo system-config-samba
远程桌面登陆ubuntu后无法使用键盘输入小写s和m
在xp上所有程序->附件->远程桌面连接 连接上Ubuntu后,发现输入字母s或m后,分别弹出logout菜单和message菜单
百度搜索结果中列出了文章的部分信息,一个关键的url:https://bugs.launchpad.net/ubuntu/+source/indicator-applet/+bug/568401
打开后,发现原来是indicator applet引起的bug具体修复步骤如下:
1.sudo apt-get install apt-show-versions (安装用于查看Ubuntu软件包版本的应用)
2.sudo apt-show-versions | grep indicator-applet (查看安装的indicator applet版本)发现安装的版本正是0.3.6,存在bug的那个版本
3.sudo apt-get install indicator-applet (更新至最新版本 0.3.7)
4.重启机器后ok
使用adb 调试串口
Android手机上很多外设是串口连接到AP的,如modem,gps。为了调试这些串口,通常需要将它们飞线接出来,用pc的串口连接调试。这样比较麻烦。
在adb shell里是可以直接调试串口的,就不用飞线了,还可以验证Android串口配置是否正确。
用usb连接Android设备调试后,在pc端输入 adb shell,连接成功后,先停止一些可能占用端口的服务,如:
stop ril-daemon停掉ril后台
然后:
busybox microcom -t 15000 -s 115200 /dev/ttyS0
-t 单位毫秒,无操作自动退出时间。
-s 单位bps,串口波特率。
ttyS0 要操作的串口。
然后打开另一个命令行窗口,输入:
adb shell cat /dev/ttyS0
然后可以在第一个窗口输入命令,在第二个窗口可以看到命令和响应。
如果没有响应,请检查Android串口配置是否正确,串口号是否对,波特率是否正确。
microcom的-t设置要合理,太短,输入命令可能输入不完就退出了,太长要等很久才退出。
必须先执行第一个窗口,再执行第二个窗口,因为不设置波特率,第二个窗口显示会有问题。
第一个窗口microcom退出后,也可以用以下方法发送命令到串口:
echo -e "AT\r\n">/dev/ttyS0
启动另外一个进程中的acitivity
Intent i = new Intent();
ComponentName cpName = new ComponentName("lee.magniwill.testserial", "lee.magniwill.testserial.MainActivity");
i.setComponent(cpName);
i.setAction("android.intent.action.MAIN");
启动同一个进程中的acitivity
Intent intent = new Intent("lee.magniwill.testserial.MainActivity");
startActivity(intent);
通过字符串来使用R下面资源的ID 值
方法一:
Resources resources=getResources(); String resStr = "weather_"+iconToday[0]; int resID = resources.getIdentifier(resStr, "drawable", getPackageName()); log("image to show: "+resStr + " id="+resID);log结果:04-13 12:17:46.509: D/WeatherForecast(2173): --- image to show: weather_7 id=2130837534 ---
方法二
try{ Field field=R.drawable.class.getField(resStr); int <span style="font-family: Arial, Helvetica, sans-serif;">resID </span>= field.getInt(new R.drawable()); log("image to show: "+resStr + " id="+resID); }catch(Exception e){ log(resStr,e.toString()); }
拦截HOME键、power键
修改文件:frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java
函数 interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
...
if (keyCode == KeyEvent.KEYCODE_HOME) {
mContext.sendBroadcast(intetn);发送一个broatcast广播, 然后在需要拦截home键的apk中接收改广播并做相应处理即可
}
...
}
power键
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
// add begin
app端可以接收 KEYCODE_POWER消息
ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
try{
String calssName = activityManager.getRunningTasks(1).get(0).topActivity.getClassName();//得到当前的activity名称
if ("com.xhw.fuctions.TakePicActivity".equals(calssName)){
//Please reset the special package name.
result |= ACTION_PASS_TO_USER;
Log.d(TAG,"detect power key in special package, pass to user!");
break;
}
}catch(NullPointerException e){
Log.d(TAG,"ingore a NullPointerException ..");
}
//add end
}
禁止系统安装其他任何apk
修改文件: /frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java
注释掉 runInstall();的调用处即可
C语言文件的读写、java语言文件的读写
FILE* fp = fopen("/storage/sdcard1/medias/config.txt","rt"); // int fread(void *ptr, int size, int nitems, FILE *stream); //返回值 int 代表真的读取了多少次 size的长度 //*ptr 数据读到哪个内存空间里面 // size 一次读取的数据的长度是多个字节 // nitmes读取多少次数据 // stream 从哪个文件里面读 int read = fread(mPoliceCode, sizeof(char)*6, 1, fp); ALOGE("!!! !!! mPoliceCode read =%d", read); char recordLen[2] = {0}; //int fseek(FILE *stream, long offset, int fromwhere); fseek(fp, 6 +1, SEEK_SET); //警号是6位,加1位换行符 read = fread(recordLen, sizeof(char)*1, 1, fp); ALOGE("!!! !!! recordLen read =%d", read); mRecordlength = atoi(recordLen); ALOGE("!!! mPoliceCode: %s, recordLen: %s, mRecordlength: %d read=", mPoliceCode, recordLen, mRecordlength, read); fclose(fp);//关闭流
private void saveConfigs() { String configFileNameString = "config.txt"; File settingsFile = new File(FileUtil.getDefStoragePath() + File.separator + "medias"+File.separator+ configFileNameString); // 如果文件不存在则创建之 log("saveConfigs = "+settingsFile.getAbsolutePath()); if (!settingsFile.exists()) { try { boolean ret = settingsFile.createNewFile(); log("saveConfigs "+settingsFile.getAbsolutePath()+" isn't exist! create it success?=" + ret); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); log("saveConfigs create "+settingsFile.getAbsolutePath()+" error! " + e.getMessage()); } } OutputStreamWriter osw = null; FileOutputStream fos = null; try { fos = new FileOutputStream(settingsFile); osw = new OutputStreamWriter(fos, "gb2312"); //写入警号 osw.write(MyApplication.policeCodeString); osw.write("\n"); //写入分段时间 osw.write(MyApplication.recordlength+""); log("saveConfigs code ="+MyApplication.policeCodeString +" recordlength=" + MyApplication.recordlength); osw.flush(); osw.close(); fos.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(osw != null) osw.close(); if(fos != null) fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
如何对手机内存中的文件数据进行读写呢?
Context提供了领个方法来打开该应用程序的数据文件夹中的文件I/O流,具体如下:
FileInputStream openFileInput(String name)打开应用程序的数据文件夹下的name文件对应的数据流
FileOutputSream openFileOutput(String name, int mode)打开应用程序数据文件夹下的name文件对应的输出流,mode指定文件打开的模式,该模式主要有一下4种:
①MODE_PRIVATE(该文件只能被当前应用程序读写)
②MODE_APPEND(以追加方式打开,可以在文件中追加内容)
③MODE_WORLD_READABLE(该文件内容可以被其他应用程序读取)
④MODE_WORLD_WRITEABLE(该文件内容可以被其他应用程序度,写)
读取文件:
假设name为要打开的文件名字
FileInputStream f = openFileInput(name);
byte[] buf = new byte[1024];
int hasRead = 0;
StringBuilder sb = new StringBuilder("");
while((hasRead = f.read(buf)>0))
{
sb.append(new String(buf, 0 , hasRead));
}
f.close();
获取文件内容字符串:sb.toString();
写文件:
假设要写入的字符串为content
FileOutputStream f = openFileOutput(name, MODE_APPEND);
PrintStream temp = new PrintStream(f);
temp.println(content);
temp.close();
注:应用程序的数据文件默认保存在/data/datea<package name>/files目录下,使用openFileInput和openFileOutput方法来打开文件输入流,输出流时,打开的都是应用程序的数据文件夹里的文件,也就是说是在手机内存中的文件,而不是SD卡中的文件。
eclipse导入andriod源码jar包路径:
现在我需要导入Setting源码到eclipse ,导入之后会有很多地方报错,未能找到相关类,需要我们导入相应jar包,现在我们如何知道需要导入哪些jar包?
路径:out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/下编译的classes.jar
android:protectionLevel 的修改 例如修改串口权限
一些需要system级别的权限,例如android.permission.SERIAL_PORT apk必须需要android:sharedUserId="android.uid.system" 的signature才可以安装,不然会报错: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE, 此时可以修改文件 frameworks/base/core/res/AndroidManifest.xml 把 - android:protectionLevel="signature|system" /> 修改为 + android:protectionLevel="normal" /> 然后其他需要SERIAL_PORT权限的apk 就可以直接安装了
通过包名获取其他包的Context实例
Context有个createPackageContext方法,可以创建另外一个包的上下文,这个实例不同于它本身的Context实例,但是功能是一样的。这个方法有两个参数:
1。packageName 包名,要得到Context的包名
2。flags 标志位,有CONTEXT_INCLUDE_CODE和CONTEXT_IGNORE_SECURITY两个选项。CONTEXT_INCLUDE_CODE的意思是包括代码,也就是说可以执行这个包里面的代码。CONTEXT_IGNORE_SECURITY的意思是忽略安全警告,如果不加这个标志的话,有些功能是用不了的,会出现安全警告。
判断是否是在漫游
private boolean isRoaming() { Boolean isRoaming = false; if(mContext == null) return isRoaming; ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); isRoaming = (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE && networkInfo.isRoaming()); Log.d(TAG, "jimbo---KeyguardStatusView isRoaming " + isRoaming); return isRoaming; }
android:layout_weight使用
只有在Linearlayout中,该属性才有效。之所以Android:layout_weight会引起争议,是因为在设置该属性的同时,设置android:layout_width为wrap_content和match_parent会造成两种截然相反的效果
android:layout_weight的真实含义是:一旦View设置了该属性(假设有效的情况下),那么该 View的宽度等于原有宽度(android:layout_width)加上剩余空间的占比!
设屏幕宽度为L,在两个view的宽度都为match_parent的情况下,原有宽度为L,两个的View的宽度都为L,那么剩余宽度为L-(L+L) = -L, 左边的View占比三分之一,所以总宽度是L+(-L)*1/3 = (2/3)L.事实上默认的View的weight这个值为0,一旦设置了这个值,那么所在view在绘制的时候执行onMeasure两次的原因就在这。
Google官方推荐,当使用weight属性时,将width设为0dip即可,效果跟设成wrap_content是一样的。这样weight就可以理解为占比了!
最合理的使用方式:当使用weight属性时,将width设为0dip
Android 获取控件的宽和高/ 如何获取控件的大小
在onCreate()里面获取控件的高度是0,//------------------------------------------------方法一 自己测量 int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); imageView.measure(w, h); int height =imageView.getMeasuredHeight(); int width =imageView.getMeasuredWidth(); textView.append("\n"+height+","+width); <div style="text-indent: 28px;"><span style="font-family: Arial, Helvetica, sans-serif;">//-----------------------------------------------方法二 </span><span style="font-family:宋体;color:#333333;"><span style="font-size: 14px; line-height: 28px; background-color: rgb(249, 249, 249);"> 注册一个ViewTreeObserver的监听回调,这个监听回调,就是专门监听绘图的,既然是监听绘图,那么我们自然可以获取测量值了,同时,我们在每次监听前remove前一次的监听,避免重复监听。 </span></span></div>ViewTreeObserver vto = imageView.getViewTreeObserver(); vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() {
<code class="java plain" style="line-height: 15.3999996185303px; font-size: 14px; white-space: pre; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; min-height: inherit !important; background: none !important;"><span style="white-space:pre"> </span>vto.removeOnPreDrawListener(</code><code class="java keyword" style="line-height: 15.3999996185303px; font-size: 14px; white-space: pre; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; font-weight: bold !important; min-height: inherit !important; color: rgb(0, 102, 153) !important; background: none !important;">this</code><code class="java plain" style="line-height: 15.3999996185303px; font-size: 14px; white-space: pre; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; margin: 0px !important; outline: 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; top: auto !important; vertical-align: baseline !important; width: auto !important; box-sizing: content-box !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; min-height: inherit !important; background: none !important;">);</code> int height = imageView.getMeasuredHeight(); int width = imageView.getMeasuredWidth(); textView.append("\n"+height+","+width); return true; } }); //-----------------------------------------------方法三 <span style="color: rgb(51, 51, 51); font-family: 宋体; font-size: 14px; line-height: 28px; background-color: rgb(249, 249, 249);">第2个方法基本相同,但他是全局的布局改变监听器,所以是最推荐使用的</span> ViewTreeObserver vto2 = imageView.getViewTreeObserver(); vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this); textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth()); } });
以上是关于android 零星调试笔记的主要内容,如果未能解决你的问题,请参考以下文章
Android逆向笔记-使用Android Studio调试Smali代码(方式一)
Android逆向笔记-使用Android Studio调试Smali代码(方式二)
Android学习笔记Android Studio简单断点调试