Android 警告：Buttons in button bars should be borderless
Android中默认情况下，几个Button并排在一个布局里会发出警告： Buttons in button bars should be borderless Buttons in button bars should be borderless; use style="?android:attr/buttonBarButtonStyle" (and ?android:attr/buttonBarStyle on the parent) Button bars typically use a borderless style for the buttons. Set the style="?android:attr/buttonBarButtonStyle" attribute on each of the buttons, and set style="?android:attr/buttonBarStyle" on the parent layout http://developer.android.com/design/building-blocks/buttons.html 网上搜得的答案： 原因：两个Buttons放在一个布局里会被判断为按钮栏，需要添加样式取消它的边框。 解决方法： 在Buttons上添加属性style="?android:attr/buttonBarButtonStyle" 。系统提示也可以在按钮的父布局上添加 style="?android:attr/buttonBarStyle" 属性 可是这样的话你的Button就没有边框了 然而你不是想让Button没有边框，只要加上属性style="@style/Widget.AppCompat.Button"或者其他样式就可以了 所以我对这种情况的理解是： 几个Button并排在一个布局里，没有设置style属性的Button会被判断为按钮栏的按钮 然而按钮栏的按钮需要取消它的边框（即添加属性style="?android:attr/buttonBarButtonStyle"） so，几个Button并排在一个布局里设置style属性就不会有问题了
import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.os.Build; import android.util.DisplayMetrics; import java.io.File; import java.lang.reflect.Method; import java.util.List; /** * apk、app 签名类 */ public class AppSignature { /** * 获取未安装Apk的签名 * * @param apkPath * @return */ public static String byApkPath(String apkPath) { String PATH_PackageParser = "android.content.pm.PackageParser"; try { // apk包的文件路径 // 这是一个Package 解释器, 是隐藏的 // 构造函数的参数只有一个, apk文件的路径 Class<?> pkgParserCls = Class.forName(PATH_PackageParser); Object pkgParser; if (Build.VERSION.SDK_INT > 19) pkgParser = pkgParserCls.newInstance(); else pkgParser = pkgParserCls.getConstructor(String.class).newInstance(apkPath); // 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况 DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); Object pkgParserPkg = null; if (Build.VERSION.SDK_INT > 19) { Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", File.class, int.class); pkgParser_parsePackageMtd.setAccessible(true); pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, new File(apkPath), PackageManager.GET_SIGNATURES); } else { Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", File.class, String.class, DisplayMetrics.class, int.class); pkgParser_parsePackageMtd.setAccessible(true); pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, new File(apkPath), apkPath, metrics, PackageManager.GET_SIGNATURES); } pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), int.class).invoke(pkgParser, pkgParserPkg, PackageManager.GET_SIGNATURES); // 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开 Signature[] info = (Signature[]) pkgParserPkg.getClass().getDeclaredField("mSignatures").get(pkgParserPkg); return info[0].toCharsString(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 获取已安装apk签名 * * @param context * @param packName * @return */ public static String byPackageName(Context context, String packName) { PackageManager pm = context.getPackageManager(); List<PackageInfo> apps = pm.getInstalledPackages(PackageManager.GET_SIGNATURES); try { return pm.getPackageInfo(packName, PackageManager.GET_SIGNATURES).signatures[0].toCharsString(); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return null; } /** * 检测签名是否相同 * * @param context * @param packName * @param apkPath * @return */ public static boolean test(Context context, String packName, String apkPath) { return byApkPath(apkPath).equals(byPackageName(context, packName)); } }
删除数据 添加数据 插入数据 替换数据 整数与二进制数据互转 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <io.h> typedef unsigned char byte; long getLength(FILE *stream) { return filelength(fileno(stream)); } bool removeBytes(FILE *stream, int length) { if (length <= 0) return true; long pos1, pos2, oldLength, newLength, off; pos1 = pos2 = ftell(stream); fseek(stream, 0, 2); oldLength = ftell(stream); fseek(stream, pos1, 0); newLength = oldLength - length; off = newLength - pos1; while (off > 0) { int cSize = off>0x1000?0x1000:off; char *cache = new char[cSize]; off -= cSize; if (fseek(stream, pos2 + length, 0) || fread(cache, 1, cSize, stream) != cSize || fseek(stream, pos2, 0) || fwrite(cache, 1, cSize, stream) != cSize) return false; pos2 += cSize; free(cache); } fseek(stream, pos1, 0); return !ftruncate(fileno(stream), newLength<pos1?pos1:newLength); } bool addBytes(FILE *stream, int length) { if (length <= 0) return true; long pos, oldLength, newLength, off; pos = ftell(stream); fseek(stream, 0, 2); oldLength = ftell(stream); fseek(stream, pos, 0); newLength = oldLength + length; off = oldLength - pos; if (ftruncate(fileno(stream), newLength)) return false; while (off > 0) { int cSize = off>0x1000?0x1000:off; char *cache = new char[cSize]; off -= cSize; if (fseek(stream, pos + off, 0) || fread(cache, 1, cSize, stream) != cSize || fseek(stream, pos + length + off, 0) || fwrite(cache, 1, cSize, stream) != cSize) return false; free(cache); } fseek(stream, pos, 0); return true; } bool insertBytes(FILE *stream, byte *bytes, long length = 4) { if (length <= 0) return true; return addBytes(stream, length) && fwrite(bytes, 1, length, stream) == length; } bool replaceBytes(FILE *stream, long length1, byte *bytes, long length2 = 4) { if (length1 < 0 || length2 < 0) return true; long length; bool boolean; length = length2 - length1; if (length > 0) boolean = addBytes(stream, length); else if (length < 0) boolean = removeBytes(stream, -length); return boolean && fwrite(bytes, 1, length2, stream) == length2; } template<typename T> void bytesToNumber(const uint8_t *bytes, T &n, size_t length = sizeof(T)) { n = 0; if (length > 0) { for (int i = 0; i < length; ++i) { n |= (bytes[i] & 0xff) << (length - 1 - i) * 8; } } } template<typename T> void numberToBytes(uint8_t *bytes, T n, size_t length = sizeof(T)) { if (bytes == nullptr) { return; } if (length > 0) { for (int i = 0; i < length; ++i) { *bytes++ = (uint8_t)(n >> (length - 1 - i) * 8 & 0xff); } } }