FLM 代理——解决因为网络问题而无法恢复内购和安装内容
FLM 代理
解决因为网络问题而无法恢复购买和安装内容。
注意: Android 7 以上设备无法使用此方法。
软件需要解压运行,不要单独运行!软件可能会报毒。
相关文件:https://pan.baidu.com/s/1H31GQ6RbUxTC1OYaoXpxlw
或 QQ 群:1054980913
软件及资源均为免费提供,只能用于学习等非盈利性质用途,不得贩卖!
......解决因为网络问题而无法恢复购买和安装内容。
注意: Android 7 以上设备无法使用此方法。
软件需要解压运行,不要单独运行!软件可能会报毒。
相关文件:https://pan.baidu.com/s/1H31GQ6RbUxTC1OYaoXpxlw
或 QQ 群:1054980913
软件及资源均为免费提供,只能用于学习等非盈利性质用途,不得贩卖!
......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));
}
}