我在项目中使用google原生的sip电话api开发网络电话的过程中,在一般手机上没有问题,当我把项目迁移到香蕉派上去测试的时候发现sipmanager.newInstance()一直返回null。
折腾了半天发现并不是权限的问题,也不是系统版本的问题。
问题出在android.software.sip.voip.xml这个文件上。
文件内容:
在香蕉派的系统中的/system/etc/permissions文件夹下并没有这个文件
解决方法:将这个文件copy到此目录中去(需要设备root)
分析原因:
我们看看SipManager.newInstance()方法
public static SipManager newInstance(Context context) { return (isApiSupported(context) ? new SipManager(context) : null); }首先会调用isApiSupported()方法判断设备是否支持sip
看看isApiSupported方法:
/** * Returns true if the SIP API is supported by the system. */ public static boolean isApiSupported(Context context) { return context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_SIP); }
执行了context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SIP)方法
很不幸这是个抽象方法
public abstract boolean hasSystemFeature(String name);
找到其实现方法
services/java/com/android/server/pm/PackageManagerService.java
public boolean hasSystemFeature(String name) {
在成员mAvailableFeatures中没有查找到PackageManager.FEATURE_SIP,返回flase。所以无法创建SipManager对象。在PackageManagerService类中,
成员变量mAvailableFeatures的值是通过读取/system/permissions下的xml文件进行设置的
private void readPermissionsFromXml(File permFile) {
FileReader permReader = null;
try {
permReader = new FileReader(permFile);
} catch (FileNotFoundException e) {
Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
return;
}
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);
XmlUtils.beginDocument(parser, "permissions");
while (true) {
XmlUtils.nextElement(parser);
if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
break;
}
String name = parser.getName();
if ("group".equals(name)) {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = Integer.parseInt(gidStr);
mGlobalGids = appendInt(mGlobalGids, gid);
} else {
Slog.w(TAG, " without gid at "
+ parser.getPositionDescription());
}
XmlUtils.skipCurrentTag(parser);
continue;
} else if ("permission".equals(name)) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, " without name at "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
continue;
}
perm = perm.intern();
readPermission(parser, perm);
} else if ("assign-permission".equals(name)) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, " without name at "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
continue;
}
String uidStr = parser.getAttributeValue(null, "uid");
if (uidStr == null) {
Slog.w(TAG, " without uid at "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
continue;
}
int uid = Process.getUidForName(uidStr);
if (uid < 0) {
Slog.w(TAG, " with unknown uid \""
+ uidStr + "\" at "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
continue;
}
perm = perm.intern();
HashSet perms = mSystemPermissions.get(uid);
if (perms == null) {
perms = new HashSet();
mSystemPermissions.put(uid, perms);
}
perms.add(perm);
XmlUtils.skipCurrentTag(parser);
} else if ("library".equals(name)) {
String lname = parser.getAttributeValue(null, "name");
String lfile = parser.getAttributeValue(null, "file");
if (lname == null) {
Slog.w(TAG, " without name at "
+ parser.getPositionDescription());
} else if (lfile == null) {
Slog.w(TAG, " without file at "
+ parser.getPositionDescription());
} else {
//Log.i(TAG, "Got library " + lname + " in " + lfile);
mSharedLibraries.put(lname, lfile);
}
XmlUtils.skipCurrentTag(parser);
continue;
} else if ("feature".equals(name)) {
String fname = parser.getAttributeValue(null, "name");
if (fname == null) {
Slog.w(TAG, " without name at "
+ parser.getPositionDescription());
} else {
//Log.i(TAG, "Got feature " + fname);
FeatureInfo fi = new FeatureInfo();
fi.name = fname;
mAvailableFeatures.put(fname, fi);
}
XmlUtils.skipCurrentTag(parser);
continue;
} else {
XmlUtils.skipCurrentTag(parser);
continue;
}