android入门之文件系统操作

(一)获取总根
File[] fileList=File.listRoots();
//返回fileList.length为1
//fileList.getAbsolutePath()为”/”
//这就是系统的总根
File[] fileList=File.listRoots(); //返回fileList.length为1 //fileList.getAbsolutePath()为”/” //这就是系统的总根
(二)打开总根目录
File file=new File(“/”);
File[] fileList=file.listFiles();

//获取的目录中除了”/sdcard”和”/system”还有”/data”、”/cache”、”/dev”等
//Android的根目录并不像Symbian系统那样分为C盘、D盘、E盘等
//Android是基于Linux的,只有目录,无所谓盘符
File file=new File(“/”); File[] fileList=file.listFiles();

//获取的目录中除了”/sdcard”和”/system”还有”/data”、”/cache”、”/dev”等 //Android的根目录并不像Symbian系统那样分为C盘、D盘、E盘等 //Android是基于Linux的,只有目录,无所谓盘符
(三)获取系统存储根目录
File file=Environment.getRootDirectory();//File file=new File(“/system”);
File[] fileList=file.listFiles();
//这里说的系统仅仅指”/system”
//不包括外部存储的手机存储的范围远远大于所谓的系统存储
File file=Environment.getRootDirectory();

//File file=new File(“/system”); File[] fileList=file.listFiles();

//这里说的系统仅仅指”/system”

//不包括外部存储的手机存储的范围远远大于所谓的系统存储
(四)获取SD卡存储根目录
File file=Environment.getExternalStorageDirectory();//File file=new File(“/sdcard”);
File[] fileList=file.listFiles();
//要获取SD卡首先要确认SD卡是否装载
boolean is=Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
//如果true,则已装载
//如果false,则未装载
File file=Environment.getExternalStorageDirectory();//File file=new File(“/sdcard”); File[] fileList=file.listFiles(); //要获取SD卡首先要确认SD卡是否装载 boolean is=Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); //如果true,则已装载 //如果false,则未装载
(五)获取data根目录
File file=Environment.getDataDirectory();//File file=new File(“/data”);
File[] fileList=file.listFiles();
//由于data文件夹是android里一个非常重要的文件夹,所以一般权限是无法获取到文件的,即fileList.length返回为0
File file=Environment.getDataDirectory();//File file=new File(“/data”); File[] fileList=file.listFiles(); //由于data文件夹是android里一个非常重要的文件夹,所以一般权限是无法获取到文件的,即fileList.length返回为0
(六)获取私有文件路径
Context context=this;//首先,在Activity里获取context
File file=context.getFilesDir();
String path=file.getAbsolutePath();
//此处返回的路劲为/data/data/包/files,其中的包就是我们建立的主Activity所在的包
//我们可以看到这个路径也是在data文件夹下
//程序本身是可以对自己的私有文件进行操作
//程序中很多私有的数据会写入到私有文件路径下,这也是android为什么对data数据做保护的原因之一
Context context=this;//首先,在Activity里获取context File file=context.getFilesDir(); String path=file.getAbsolutePath(); //此处返回的路劲为/data/data/包/files,其中的包就是我们建立的主Activity所在的包 //我们可以看到这个路径也是在data文件夹下 //程序本身是可以对自己的私有文件进行操作 //程序中很多私有的数据会写入到私有文件路径下,这也是android为什么对data数据做保护的原因之一
(七)获取文件(夹)绝对路径、相对路劲、文件(夹)名、父目录
File file=……
String relativePath=file.getPath();//相对路径
String absolutePath=file.getAbsolutePath();//绝对路径
String fileName=file.getName();//文件(夹)名
String parentPath=file.getParent();//父目录
File file=…… String relativePath=file.getPath();//相对路径 String absolutePath=file.getAbsolutePath();//绝对路径 String fileName=file.getName();//文件(夹)名 String parentPath=file.getParent();//父目录
(八)列出文件夹下的所有文件和文件夹
File file=……
File[] fileList=file.listFiles();
File file=…… File[] fileList=file.listFiles();
(九)判断是文件还是文件夹
File file=……
boolean is=file.isDirectory();//true-是,false-否
File file=…… boolean is=file.isDirectory();//true-是,false
(十)判断文件(夹)是否存在
File file=……
boolean is=file.exists();//true-是,false-否
File file=…… boolean is=file.exists();//true-是,false-否
(十一)新建文件(夹)
File file=……
oolean is=file.isDirectory();//判断是否为文件夹
/*方法1*/
if(is){
String path=file.getAbsolutePath();
String name=”ABC”;//你要新建的文件夹名或者文件名
String pathx=path+name;
File filex=new File(pathx);
boolean is=filex.exists();//判断文件(夹)是否存在
if(!is){
filex.mkdir();//创建文件夹
//filex.createNewFile();//创建文件
}
/*方法2*/
if(is){
String path=file.getAbsolutePath();
String name=”test.txt”;//你要新建的文件夹名或者文件名
File filex=new File(path,name);//方法1和方法2的区别在于此
boolean is=filex.exists();//判断文件(夹)是否存在
if(!is){
filex.mkdir();//创建文件夹
//filex.createNewFile();//创建文件
}
File file=…… oolean is=file.isDirectory();//判断是否为文件夹 /*方法1*/ if(is){ String path=file.getAbsolutePath(); String name=”ABC”;//你要新建的文件夹名或者文件名 String pathx=path+name; File filex=new File(pathx); boolean is=filex.exists();//判断文件(夹)是否存在 if(!is){ filex.mkdir();//创建文件夹 //filex.createNewFile();//创建文件 } /*方法2*/ if(is){ String path=file.getAbsolutePath(); String name=”test.txt”;//你要新建的文件夹名或者文件名 File filex=new File(path,name);//方法1和方法2的区别在于此 boolean is=filex.exists();//判断文件(夹)是否存在 if(!is){ filex.mkdir();//创建文件夹 //filex.createNewFile();//创建文件 }
(十二)重命名文件(夹)
File file=……
String parentPath=file.getParent();
String newName=”name”;//重命名后的文件或者文件夹名
File filex=new File(parentPath,newName);//File filex=new File(parentPaht+newName)
file.renameTo(filex);
File file=…… String parentPath=file.getParent(); String newName=”name”;//重命名后的文件或者文件夹名 File filex=new File(parentPath,newName);//File filex=new File(parentPaht+newName) file.renameTo(filex)
(十三)删除文件(夹)
File file=……
file.delete();//立即删除
//file.deleteOnExit();//程序退出后删除,只有正常退出才会删除

(十四)获得所有可存储的路径,可能包括手机内置的SD卡和外置的SD卡

(不同手机Environment.getExternalStorageDirectory()获得路径不一样)

String starageStr = “”;

StorageManager sm = (StorageManager)context.getSystemService(Context.STORAGE_SERVICE);
try {
String[] paths = (String[]) sm.getClass().getMethod(“getVolumePaths”, null).invoke(sm, null);
for (int i = paths.length – 1; i > -1; i–) {
String status = (String) sm.getClass()
.getMethod(“getVolumeState”, String.class).invoke(sm, paths[i]);
if (status.equals(android.os.Environment.MEDIA_MOUNTED)) {
// SDCARD_PATH = paths[i];
// break;
starageStr+=paths[i];
}
}
} catch (Exception e) {}

(十五)下载缓存目录

File downloadCacheDir = Environment.getDownloadCacheDirectory();

(十六)检查设备的外存是否是内存模拟的

boolean isEmu = Environment.isExternalStorageEmulated();

(十七)检查外存是否是可拆卸的

boolean canRemoved = Environment.isExternalStorageRemovable();

后台线程如何正确发送消息(来自内网)

作者:xuding 转过来作为记录。

由于历史原因,我们有的APP依然使用webservice进行网络请求,我们为此封装了WebserviceUtils工具类,这个类具有明显的工具类特点——不与界面业务有任何耦合,这本应是个不错的设计。
然而我们长大后确发现,正因为不与界面耦合,WebserviceUtils在请求操作出错时,无法向界面传递消息,起初我们纠结万分,痛苦之中在研究了android Looper类的源码,于是我们自以为掌握了android消息队列的原理,参考:
http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html
于是有了如下代码:

01.try {

02. // 网络请求

03.} catch (Exception e) {

04. Log.e(TAG, “请求超时”, e);

05. Activity activity = ActivityStackManager.getCurrentActivity();

06. Looper.prepare();

07. SysUtils.closeHint();

08. Toast.makeText(activity, “网络通讯异常,请检查网络…”, Toast.LENGTH_LONG).show();

09. Looper.loop();

10.}
复制代码这样书写终于可以弹出提示了,然而悲剧的是,弹出提示紧接着,界面就失去响应(ANR),曾记否,那一年的冬天,大约也是这个季节,当时客户现场不断传来APP停止响应的呼吼,出错现象如同雪花在面前纷纷扬扬,而我们居然一片都抓不住啊
说正题,此处的问题很经典,需要从后台线程向界面上展示消息,Android展示消息只能在主线程里操作。Android中每个线程都有handler对象,消息框(Toast)、对话框等都是通过主线程的handler操作消息对列来做的。
上述代码中的Looper.prepare()、Looper.loop()是参考Handler.java源码来做的,那么为什么会ANR呢?
关键就是这里的loop(),和其他系统一样,android的消息队列也是通过死循环实现的:

01.for (;;) {

02. Message msg = queue.next(); // might block

03. if (msg == null) {

04. // No message indicates that the message queue is quitting.

05. return;

06. }

07. msg.target.dispatchMessage(msg);

08. // 。。。。。

09. msg.recycle();

10.}
复制代码低版本sdk中是while(){…),都一样,在后台线程loop()之后,因为这个死循环,该线程就一直处于阻塞状态了,于是这里的消息也就成了APP临终的遗言,紧接着ANR失去响应,然后就没有然后了。。。因为是死循环导致出错,所以APP捕获不到uncaughtException,也就无法输出错误日志了,于是更加让人不明所以,加大了排查错误的难度。
那么问题来了,后台线程究竟有没有办法向前台发消息呢?当然有,其实我们有了上述的知识,离胜利已经很近了:

01.new Handler(Looper.getMainLooper()).post(new Runnable() {

02. @Override

03. public void run() {

04. SysUtils.closeHint();

05. Toast.makeText(activity, “网络通讯异常,请检查网络…”, Toast.LENGTH_LONG).show();

06. }

07.});
复制代码非常优雅的通过Looper.getMainLooper()得到主线程handler,然后post!
非常简单吧!这个故事告诉我们一个道理,凡事一要求甚解,知其然还要知其所以然。我们有时候闭门造车容易将自己蒙蔽,吾尝终日而思,不如须臾之所学也。当我们脚踏实地,蓦然回首,就会发现,原来希望一直都在我们身边,只是我们被雪花迷失了方向。。。
万幸的是,这样的错误,我们以后的APP开发中很难再出现了,我们使用的annotations框架可以很优雅的处理各种对话框,从此Looper.loop()、AnsyncTask、Handler都成为了过往的种种。。。
其实Annotations处理主线程事件,也是通过上面的new Handler(Looper.getMainLooper()).post(…)来做的,欲知Annotations如何,且听下回分解~

解决IllegalStateException: Can not perform this action after onSaveInstanceState

今天使用Fragment的时候,出现了这个错误 IllegalStateException: Can not perform this action after onSaveInstanceState:
E/AndroidRuntime(12747): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1314)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1325)

是在使用FragmentTransition的 commit方法添加一个Fragment的时候出现的,后来在官网找到了相关的
说明:http://developer.android.com/reference/android/app/FragmentTransaction.html#commitAllowingStateLoss()
public abstract int commitAllowingStateLoss () Added in API level 11

Like commit() but allows the commit to be executed after an activity’s state is saved. This is dangerous

because the commit can be lost if the activity needs to later be restored from its state, so this should

only be used for cases where it is okay for the UI state to change unexpectedly on the user.

大致意思是说我使用的 commit方法是在Activity的onSaveInstanceState()之后调用的,这样会出错,因为onSaveInstanceState
方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后再给它添加Fragment就会出错。解决办法就
是把commit()方法替换成 commitAllowingStateLoss()就行了,其效果是一样的。

转自:http://blog.csdn.net/ranxiedao/article/details/8214936

Android NFC Links

基于Android平台的NFC技术的应用实现:http://www.ctiforum.com/html/tougaozhuanlan/zuixinlaigao/349587.html

Android系统上十款最佳NFC标签应用:http://mobile.163.com/13/0913/08/98L0D7RG0011671M.html

笔记之NFC近距离无线通讯技术(Dean):http://yelinsen.iteye.com/blog/1018678

Android NFC 开发实例:http://blog.csdn.net/pku_android/article/details/7430788

APP nfcard源码:https://code.google.com/p/nfcard/source/checkout

NFC Demo及有用链接:http://download.csdn.net/detail/xxhjd/5214162

怎样使用NFC:http://bbs.xiaomi.cn/thread-8477165-1-1.html

android平台上读写NFC标签代码:http://blog.csdn.net/yeruby/article/details/9287337

android平台获取手机IMSI,IMEI ,序列号和手机号的方法(转)

1)获取运营商sim卡imsi号,

String IMSI =android.os.SystemProperties.get(

android.telephony.TelephonyProperties.PROPERTY_IMSI);

2)获取IME标识两种方法(手机唯一的标识)

String imei =((TelephonyManager) context.getSystemService(TELEPHONY_SERVICE)).getDeviceId();

String IMEI =android.os.SystemProperties.get(android.telephony.TelephonyProperties.PROPERTY_IMEI)

不过纯APP开发SystemProperties,TelephonyProperties汇报错误,因为android.os.SystemProperties在SDK的库中是没有的,需要把Android SDK 目录下data下的layoutlib.jar文件加到当前工程的附加库路径中,就可以Import。

如果Android Pad没有IMEI,用此方法获取设备ANDROID_ID:

String android_id = Secure.getString(this.getContentResolver(),Secure.ANDROID_ID);

2. 获取手机号

TelephonyManager tm=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

String number = tm.getLine1Number();

如下使用例子:

public static String getIMEI() {

return ((TelephonyManager)AppXiKang.getApp().getSystemService(

Context.TELEPHONY_SERVICE)).getDeviceId();

}

public static String getAndroidId() {

return android.provider.Settings.Secure.getString(

AppXiKang.getApp().getContentResolver(),

android.provider.Settings.Secure.ANDROID_ID);

}

public static String getSimSerialNumber() {

return ((TelephonyManager)AppXiKang.getApp().getSystemService(

Context.TELEPHONY_SERVICE)).getSimSerialNumber();

}

public static String getSerialNumber1() {

returnandroid.os.Build.SERIAL;

}

/**

* getSerialNumber

* @return result is same to getSerialNumber1()

*/

public static String getSerialNumber(){

String serial = null;

try {

Class c =Class.forName(“android.os.SystemProperties”);

Method get =c.getMethod(“get”, String.class);

serial = (String)get.invoke(c, “ro.serialno”);

} catch (Exception e) {

e.printStackTrace();

}

return serial;

}

public static void displayDevice(){

String dest_imei = getIMEI();

String androidId =getAndroidId();

Log.i(TAG, “isTestDevice:”

+”\nIMEI:”+dest_imei

+” \nANDROID ID:” +androidId

+” \nSerialNumber:”+ getSerialNumber()

+”\nSimSerialNumber:” + getSimSerialNumber()

);

}

运行结果示例:

IMEI:868331011992179

ANDROID ID:5a3b287f2b13bef8

SerialNumber:021YLJ212C001879

SimSerialNumber:898600810110

3. 获取一个能唯一标识每台Android设备的序号与服务器通信

所以如果你想得到设备的唯一序号, TelephonyManager.getDeviceId() 就足够了。但很明显暴露了DeviceID会使一些用户不满,所以最好把这些id加密了。实际上加密后的序号仍然可以唯一的识别该设备,并且不会明显的暴露用户的特定设备,例如,使用 String.hashCode() ,结合UUID:

String getuniqueId(){

TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);

Stringimei=tm.getDeviceId();

StringsimSerialNumber=tm.getSimSerialNumber();

String androidId =android.provider.Settings.Secure.getString(

getContentResolver(),android.provider.Settings.Secure.ANDROID_ID);

UUID deviceUuid =newUUID(androidId.hashCode(), ((long)imei.hashCode() << 32) |simSerialNumber.hashCode()); String uniqueIuniqueId d= deviceUuid.toString(); returnuniqueId; } 最后的deviceID可能是这样的结果: 00000000-54b3-e7c7-0000-000046bffd97 得到设备独一无二的标识: 可以用于客户端与服务端通信的唯一标识 根据测试: · 所有的设备都可以返回一个TelephonyManager.getDeviceId() · 所有的GSM设备(测试设备都装载有SIM卡) 可以返回一个TelephonyManager.getSimSerialNumber() · 所有的CDMA 设备对于 getSimSerialNumber() 却返回一个空值! · 所有添加有谷歌账户的设备可以返回一个 ANDROID_ID · 所有的CDMA设备对于 ANDROID_ID 和 TelephonyManager.getDeviceId()返回相同的值(只要在设置时添加了谷歌账户) · 目前尚未测试的:没有SIM卡的GSM设备、没有添加谷歌账户的GSM设备、处于飞行模式的设备。 转自:http://blog.csdn.net/easy_gemini/article/details/8613659