Android获取外接SD卡或者U盘路径方法

最近在开发Android时遇到插U盘获取U盘内容的需求,但是按照传统的Environment.getExternalStorageDirectory()只能读取到插入的SD卡的路径,如果是U盘的话无法读出U盘的路径。

最终在一个在CSDN的论坛里找到相关的东西,就试了下直接通过StorageManager获取存储路径的。

核心如下,volumePaths的数组就是系统外接设备的路径,经过测试的确是挂载的路径。不过有些是不可用的,它只是列出了系统可支持的外接路径。

final StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
String[] volumePaths = new String[0];
try {
	final Method method = sm.getClass().getMethod("getVolumePaths");
	if(null != method) {
		method.setAccessible(true);
		volumePaths = (String[]) method.invoke(sm);
	}
}catch (Exception e){
	e.printStackTrace();
}
if ((volumePaths != null) && (volumePaths.length > 0)){
	for (String sdcardPath : volumePaths){
		Log.d(TAG,"sdcardPath:" + sdcardPath);
	}
}

参考链接


android获取外接SD卡或者U盘路径方法

NoClassdefFoundError R$layout

工程引入了jar包,jar包使用了R.layout.xx,但这个layout并没有打进jar包导致找不到R.layout.xx。

It's because inside JAR doesn't contain resource folder of SDK Project.

解决方法有两种:

  1. 导入SDK Project,并以lib的形式依赖。

    如果要把jar包提供出去,则需要使用方法2

  2. 首先,使用下面的方法替代R(在SDK中,R自动为SDK的包名,引入他人工程后肯定找不到这个R,所以不能在SDK中使用R)

    public static int getResourseIdByName(String packageName, String className, String name) {
    Class r = null;
    int id = 0;
    try {
    r = Class.forName(packageName + ".R");

    Class[] classes = r.getClasses();
    Class desireClass = null;

    for (int i = 0; i < classes.length; i++) {
    if(classes[i].getName().split("\\$")[1].equals(className)) {
    desireClass = classes[i];

    break;
    }
    }

    if(desireClass != null)
    id = desireClass.getField(name).getInt(desireClass);
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (IllegalArgumentException e) {
    e.printStackTrace();
    } catch (SecurityException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (NoSuchFieldException e) {
    e.printStackTrace();
    }

    return id;

    }

    举例,如果以前使用了 R.layout.main,现在需要使用getResourseIdByName(context.getPackageName(), "layout", "main")      以前使用了R.id.mView,现在需要使用getResourseIdByName(context.getPackageName(), "id", "mView")

然后,把用到的资源从SDK中copy到Apk工程。

源自http://stackoverflow.com/questions/14373004/java-lang-noclassdeffounderror-com-facebook-android-rlayout-error-when-using-f

 

Android 获取签名,MD5指纹

获取指定已安装完整签名信息,包括MD5指纹:

public void getSingInfo() {  
	try {  
		PackageInfo packageInfo = getPackageManager().getPackageInfo("com.sina.weibo", PackageManager.GET_SIGNATURES);  
		Signature[] signs = packageInfo.signatures;  
		Signature sign = signs[0];  
		parseSignature(sign.toByteArray());  
	} catch (Exception e) {  
		e.printStackTrace();  
	}  
}  
public void parseSignature(byte[] signature) {  
	try {  
		CertificateFactory certFactory = CertificateFactory.getInstance("X.509");  
		X509Certificate cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(signature));  
		String pubKey = cert.getPublicKey().toString();  
		String signNumber = cert.getSerialNumber().toString();  
		System.out.println("signName:" + cert.getSigAlgName());  
		System.out.println("pubKey:" + pubKey);  
		System.out.println("signNumber:" + signNumber);  
		System.out.println("subjectDN:"+cert.getSubjectDN().toString());  
	} catch (CertificateException e) {  
		e.printStackTrace();  
	}  
}

参考链接


android获取APK签名信息及MD5指纹

Android获得内存信息

在Android中,想要获得进程内存信息,有两类方法

1.exec大法,使用Runtime.getRuntime().exec()方法来执行命令行,主要命令行有 dumpsys(需要system权限)  cat /proc等

private String catProc() {
StringBuilder meminfo = new StringBuilder();
try {
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("cat");
// commandLine.add("/proc/meminfo");
commandLine.add("/proc/" + android.os.Process.myPid() + "/status");

Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[commandLine.size()]));
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

String line;
while ((line = bufferedReader.readLine()) != null) {
meminfo.append(line);
meminfo.append("\n");
}

} catch (IOException e) {
Log.e(TAG, "Could not read /proc/meminfo", e);
}

Log.i(TAG, "showMeminfo = " + meminfo.toString());

return meminfo.toString();
}

2.android.os.Debug

Debug类有大量的获取内存信息方法,如getPss,用起来很简单

 

使用jar包中的service

要使用jar包或lib中的service,

假如 app包名为 com.app.xx

jar包名为 com.jar.xx

需要在当前app的manifest中声明service,且使用jar包中的包名,全路径,

android:name="com.jar.xx.xxService"

同时声明exported为true

android:exported="true"

<service
android:name="com.jar.xx.xxService"
android:enabled="true"
android:exported="true" />

之后就可以使用am指令打开/关闭service了

打开service ()
adb shell am startservice -n com.app.xx/com.jar.xx.xxService
关闭service
1.adb shell am stopservice -n com.app.xx/com.jar.xx.xxService
2.可能android低版本会不支持 stopservice命令。备用关闭方法: adb shell am force-stop com.app.xx (会关闭整个进程,用kill进程不行,service会自动重启)

IPFire的Web管理页面中增加中文语言

1.在语言列表中增加中文选项

$ vim /var/ipfire/langs/list

在最后面增加zh:简体中文:中国,最后的内容如下所示:

en:English:English
de:Deutsch:German
fr:Français:French
es:Español:Spanish
pl:Polski:Polish
ru:Русский:Russian
nl:Nederlands:Dutch
tr:Türkçe:Turkish
it:Italiano:Italian
zh:简体中文:中国

2.复制英文语言文件为中文文件

$ cp /var/ipfire/langs/en.pl /var/ipfire/langs/zh-cn.pl

3.修改需要显示的英文为中文,注意,里面的内容,前面为键值,后面为显示的内容,比如:

'Class' => 'Class'

修改为:

'Class' => '分类'

4.修改完成后,刷新语言文件缓存

$ perl -e "require '/var/ipfire/lang.pl'; &Lang::BuildCacheLang"

5.在网页中的GUI Setings中选择语言为简体中文即可。

参考链接


Creating language file

修改IPFire内网网卡地址

IPFire内网网卡地址一旦设置完成后,在Web控制的主界面中,是找不到修改的地方的,因此,只能在命令行中重新调用设置命令来重新配置。

Web页面中开启SSH Access,以支持Shell进行控制

IPFireWebGuiSSHAccess

IPFireWebGuiSSHAccessSSHConfigure

Shell的登陆界面中输入setup界面,唤出设置界面:

IPFireSetupCommand

接下来,就是一步步的设置了

IPFireSetupCommandMenu

参考链接


Changing the "Green IP Address of IP fire"

开源防火墙IPFire的配置

IPFireLinux源代码建立的防火墙,并且还带有大量的附加功能。它易于设置和管理。它采用的状态检测防火墙,内容过滤引擎,通信质量控制(QoS),VPN技术,和大量的记录。IPFire是基于模块化设计具有高度的灵活性,最重要它是开源的并且基于状态检测的防火墙。你可以到http://www.ipfire.org/downloads下载安装镜像。
DownloadIPFireWebSite 一.下面是用Virtual Box虚拟机安装过程,首先新建一个虚拟机VirtualBoxNewIPFire_x64_1二.选择下载好的镜像文件 IPFireIsoImage_x86_64

2.1在这里需要注意,安装IPFire至少要有两张网卡 ,分别绑定到两个个区域(下面会讲到)
VirtualBox_NetWorkCard_1

VirtualBox_NetWorkCard_2

三.运行虚拟机,进入安装画面,键入Enter继续 IPFireInstallView1 四.选择安装语言,没有中文 = = IPFireInstallViewLanaguage

IPFireInstallViewStartInstalltion

IPFireInstallViewLicense

五.选择安装到哪些硬盘,确定是否进行分区

IPFireInstallViewDeleteAllData

六.选择文件系统,默认ext4即可。IPFireInstallViewFileSytem

七.安装完成RebootIPFireInstallViewReboot

八.重启进行选择界面 IPFireViewLanuch

九.对IPFire进行初始化(键盘,时区,主机名,系统密码,web管理密码,安全区域等)

9.1 键盘布局

IpFireSettingKeyBoard

9.2 时区选择

IpFireSettingTimeZone

9.3 主机名设置

IPFireSettingHostName

9.4 域名称设置

IPFireSettingDomainName

9.5 系统密码设置(root)

IPFireSettingRootPassword

9.6 Web管理密码设置(admin)

IPFireSettingAdminPassword

9.7 安全区域设置

IPFireSettingNetworkConfiguration

IPFireSettingNetworkConfigurationType

IPFire把网络分为不同的颜色代表一个共同的计算机的安全等级:

  • 绿色 代表一个安全的地方。这就是所谓咱们的内网。
  • 红色 代表一般危险,就是所谓的互联网
  • 蓝色 代表了无线局域网络的一部分。
  • 橙色 通常被称为非军事区(DMZ)。

9.8 将两张网卡关联到两个安全区域上

IPFireSettingNetworkConfigurationDeiversAndCardAssignments

IPFireSettingNetworkConfigurationAssignedCards 

IPFireSettingNetworkConfigurationAssignedCardsFinal

9.9 分别设置两个区域的IP地址

IPFireSettingNetworkConfigurationMenuAddressSettings

IPFireSettingNetworkConfigurationAddressSettings

9.10 RED区域就是所谓的外网,可以用三种方式(静态,DHCP, PPPOE),此处的外网,我们直接使用DHCP来分配即可。

IPFireSettingInterfaceRed

IPFireSettingInterfaceRedDHCP

9.11 设置DNS和网关地址

IPFireSettingInterfaceGreen

IPFireSettingGreenInterfaceIPAddress

9.12 最后是否为内网启用DHCP功能

IPFireSettingGreenInterfaceDHCPServerConfiguration

十. 完成后,用浏览器访问https://green接口地址:444,用admin帐号登陆.Red网卡的地址是不能通过外网来访问的。

IPFireMainPage

参考链接


Windows 路径相关的ShellApi

路径截断与合并函数
PathRemoveArgs 去除路径的参数
PathRemoveBackslash 去除路径最后的反斜杠"\"
PathAddBackslash 在路径最后加上反斜杠"\"
PathRemoveBlanks 去除路径前后的空格
PathAddExtension 在文件路径后面加上扩展名
PathRemoveExtension 去除文件路径扩展名
PathRenameExtension 更改文件路径扩展名
PathRemoveFileSpec 去除文件名,得到目录
PathUnquoteSpaces 去除路径中的首尾空格
PathQuoteSpaces 判断路径中是否有空格,有的话,就是用""引号把整个路径包含起来
PathAppend 将一个路径追加到另一个路径后面
PathCombine 合并两个路径
PathSkipRoot 去掉路径中的磁盘符或UNC部分。
PathStripPath 去掉路径中的目录部分,得到文件名。
PathStripToRoot 去掉路径的文件部分,得到根目录。
   
PathCompactPath 根据像素值生成符合长度的路径。如原始路径:C:\path1\path2\sample.txt
根据120像素截断后为:C:\pat...\sample.txt
根据25像素截断后为: ...\sample.txt
PathCompactPathEx 根据字符个数来生成符合长度的路径。
   
PathSetDlgItemPath 将路径数据设置到对话框的子控件上。
PathUndecorate 去除路径中的修饰——具体还没看明白,的例子只是去掉了括号。
PathUnExpandEnvStrings 将路径中部分数据替换为系统环境变量格式
路径查找比较函数
PathFindOnPath 从路径中查找路径
PathFindExtension 查找路径的扩展名
PathFindFileName 获取路径的文件名
PathFindNextComponent 查找匹配路径(不太熟悉)
PathFindSuffixArray 查找给定的文件名是否有给定的后缀。
PathGetArgs 获取路径参数
PathGetCharType 获取路径字符类型
PathGetDriveNumber 根据逻辑盘符返回驱动器序号
路径转换函数
PathRelativePathTo 创建一个路径到另一个路径的相对路径。
PathResolve 将一个相对路径或绝对路径转换为一个合格的路径,这个理解起来比较拗口。
PathCanonicalize 规范化路径。将格式比较乱的路径整理成规范的路径格式。
PathBuildRoot 根据给定的磁盘序号创建根目录路径
CreateDirectory 创建目录
   
GetShortPathName 将长路径转为8.3格式的短路径格式
GetLongPathName 将短路径格式转为长路径。
PathGetShortPath 将长路径转为短路径格式(8.3格式)
PathCreateFromUrl 将URL路径转为MS-DOS格式
PathMakePretty 把路径全部转为小写,增加可读性。
PathMakeSystemFolder 给路径增加系统属性
PathUnmakeSystemFolder 去除路径中的系统属性。
PathMakeUniqueName 从模板创建统一的路径格式——没用过,不熟悉
PathProcessCommand 生成一个可执行的路径,比如有参数的,会自动将路径用""包含。这在ShellExecute中比较有用。
路径验证函数
PathCleanupSpec 去除路径中不合法的字符
PathCommonPrefix 比较并提取两个路径相同的前缀
PathFileExists 验证路径是否存在
PathMatchSpec 判断路径是否匹配制定的扩展名。
PathIsDirectory 判断路径是否是一个有效的目录
PathIsFileSpec 验证路径是否一个文件名(有可能是一个路径)
PathIsExe 验证路径是否是可执行文件。注意:不仅仅是.exe,还有.bat,.com,.src等
PathIsRoot 路径是否为根路径
PathIsRelative 判断路径是否是相对路径
PathIsContentType 检测文件是否为制定类型。
例如:PathIsContentType("hello.txt", "text/plain") 返回TRUE
PathIsContentType("hello.txt", "image/gif") 返回FALSE
PathIsHTMLFile 判断路径是否是html文件类型——根据系统注册类型判断。
PathIsLFNFileSpec 判断路径是否是长路径格式
PathIsNetworkPath 判断路径是否是一个网络路径。
PathIsPrefix 判断路径是否含有指定前缀
PathIsSameRoot 判断路径是否有相同根目录
PathIsSlow 判断路径是否是一个高度延迟的网络连接——我也不太明白是啥意思。
PathIsSystemFolder 判断路径是否有系统属性(属性可以自己设定)
PathIsUNC 路径是否是UNC格式(网络路径)
PathIsUNCServer 路径是否是UNC服务器
PathIsUNCServerShare 路径是否仅仅是UNC的共享路径格式
PathIsURL 路径是否是http格式。
PathYetAnotherMakeUniqueName 基于已存在的文件,自动创建一个唯一的文件名。比较有用,比如存在"新建文件",此函数会创建文件名"新建文件(2)"。

参考链接


windows 路径相关的shell api

在Visual C++ 2015 中使用Tab Control控件

系统环境:Windows 7
软件环境:Visual Studio 2015 Udpate 2
本次目的:在模态或非模态对话框中使用Tab Control控件,及引申在单/多文档中使用

查阅MSDN文档,对于创建Tab Control控件,MSDN上说明如下:

To use CTabCtrl directly in a dialog box
1. In the dialog editor, add a Tab Control to your dialog template resource. Specify its control ID.
2. Use the Add Member Variable Wizard to add a member variable of type CTabCtrl with the Control property. You can use this member to call CTabCtrl member functions.
3. Map handler functions in the dialog class for any tab control notification messages you need to handle. For more information, see Mapping Messages to Functions.
4. In OnInitDialog, set the styles for the CTabCtrl .
To use CTabCtrl in a nondialog window
1. Define the control in the view or window class.
2. Call the control's Create member function, possibly in OnInitialUpdate, possibly as early as the parent window's OnCreate handler function (if you're subclassing the control). Set the styles for the control.

 

对话框内使用CTabCtrl


1. 在对话框编辑区内,添加一个Tab Control控件到资源模板里面,设置它的控制ID
2. 使用添加成员变量向导,为控件添加一个CTabCtrl类型的成员变量,你可以使用这个变量调用CTabCtrl的成员函数
3. 对话框类的映射处理功能可以处理任何你需要处理的标签控件消息。有关更多信息,请参阅消息映射函数。
4. 在OnInitDialog()函数里面,设置CTabCtrl的风格。

非对话框窗口使用CTabCtrl


1. 定义在视图或窗口类的控件。
2. 调用控件的创建成员函数,可能在OnInitialUpdate中,可能在父窗口的OnCreate处理函数早期(如果你是子类的控件)。设置控件的风格。
下面介绍在对话框中添加Tab Control控件,工程不一定是要MFC基于对话框形式,单文档视图类派生自 CFormView的工程也行,或是任何工程弹出的对话框 ( 如登录界面等等 ) 都行 ( 个人没有都去实验,但理论上应该可以,看了下面就知道。 )
1. 首先在对话框资源上添加一个Tab Control控件IDIDC_LOGIN_TAB,根据需要修改其属性,然后为其添加成员变量m_tab,类型为CTabCtrl
2. 需要几个选项卡,则在对话框资源添加几个对话框,在这里我添加两个选项卡,则要添加两个对话框,其ID分别为 IDD_TAB1_DIALOGIDD_TAB2_DIALOG它们的属性styleChild,BorderNone,其他的再根据自己调整。然后分别为其添加对应的基于CDialogCLoginTab1CLoginTab2
3. 在主对话框添加子对话框头文件,然后再添加三个成员变量,为子对话框添加实例。在OnInitDialog()函数初始化Tab Control控件显示,若对话框没有OnInitDialog()函数,则重载这个函数,具体如下:
//主对话框头文件

class LoginUser : public CDialog
{
	...
	protected:
	virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
	virtual BOOL OnInitDialog(); //没有这个,则在这里重载
	DECLARE_MESSAGE_MAP()
	public:
	CTabCtrl m_tab;
	CLoginTab1 m_login_tab1;
	CLoginTab2 m_login_tab2;
	...
}

//主对话框实现文件

BOOL LoginUser::OnInitDialog()
{
	CDialog::OnInitDialog();
	m_tab.InsertItem(0,_T("系统登录"));
	m_tab.InsertItem(1,_T("服务器设置"));
	m_login_tab1.Create(IDD_TAB1_DIALOG,GetDlgItem(IDC_LOGIN_TAB));
	m_login_tab2.Create(IDD_TAB2_DIALOG,GetDlgItem(IDC_LOGIN_TAB));
	//获得IDC_TABTEST客户区大小
	CRect rs;
	m_tab.GetClientRect(&rs);
	//调整子对话框在父窗口中的位置,根据实际修改
	rs.top+=25;
	rs.bottom-=60;
	rs.left+=1;
	rs.right-=10;

	//设置子对话框尺寸并移动到指定位置
	m_login_tab1.MoveWindow(&rs);
	m_login_tab2.MoveWindow(&rs);
	//分别设置隐藏和显示
	m_login_tab1.ShowWindow(true);
	m_login_tab2.ShowWindow(false);

	//设置默认的选项卡
	m_tab.SetCurSel(0);
	return TRUE;
}

4. 响应选项卡切换事件消息,右键Tab Control控件,添加事件处理程序,选择TCN_SELCHANGE事件,在弹出的编辑区域,填入以下代码:

void LoginUser::OnTcnSelchangeLoginTab(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	int CurSel = m_tab.GetCurSel();
	switch(CurSel)
	{
	case 0:
	m_login_tab1.ShowWindow(true);
	m_login_tab2.ShowWindow(false);
	break;
	case 1:
	m_login_tab1.ShowWindow(false);
	m_login_tab2.ShowWindow(true);
	break;
	default: ;
	}
	*pResult = 0;
}

5. 编译运行。

22

接下来,来看看非模态对话框的实现,因为Tab Control控件要在对话框的OnInitDialog()函数初始化,而MSDN上说:

After the dialog box and all of its controls are created but just before the dialog box (of either type) appears on the screen, the dialog object's OnInitDialog member function is called. For a modal dialog box, this occurs during the DoModal call. For a modeless dialog box, OnInitDialog is called when Create is called. You typically override OnInitDialog to initialize the dialog box's controls, such as setting the initial text of an edit box. You must call the OnInitDialog member function of the base class, CDialog , from your OnInitDialog override.

非模态对话框是在Create的时候一起调用初始化函数的,OnInitDialog()我们仍可以重载这个函数,来实现以上功能。对于单文档/多文档可以看前面的MSDN说明,这里不再详细写。本文若有错误,请指出。

参考链接


在VC++中使用Tab Control控件