我想创建一个可以在安装我的应用程序后更改galaxy手机中的系统字体样式的应用程序用户可以从设置>我的设备>字体样式更改字体,并从列表中选择而无需root权限。我在真实类型文件中有自己的字体样式。 点击here查看我想要制作的应用示例。
唐氏投票不会帮助请回答或不投票。
manidest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="2" android:versionName="1.1" package="com.monotype.android.font.presentltroman" platformBuildVersionCode="23" platformBuildVersionName="6.0-2438415">
<uses-sdk android:minSdkVersion="7" />
<application android:label="@string/app_name" android:icon="@drawable/icon">
<provider android:name=".FontContentProvider" android:authorities="com.example.myfont" />
<support-screens android:largeScreens="true" android:xlargeScreens="true" />
</application>
</manifest>
只有一项活动
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.FileNotFoundException;
public class FontContentProvider extends ContentProvider {
private static final UriMatcher uriMatcher = new UriMatcher(-1);
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
return null;
}
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
String file_name = uri.getPath();
if (file_name == null) {
throw new FileNotFoundException();
}
if (file_name.startsWith("/")) {
file_name = file_name.substring(1);
}
AssetFileDescriptor ad = null;
try {
ad = getContext().getAssets().openFd(file_name);
} catch (Exception e) {
Log.v("CPFontTest", "cp - openAssetFile EXCEPTION");
}
return ad;
}
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
public String getType(Uri uri) {
AssetManager am = getContext().getAssets();
StringBuilder xmlfileStringBuilder = new StringBuilder();
try {
for (String s : am.list("xml")) {
xmlfileStringBuilder.append(s + "\n");
}
return xmlfileStringBuilder.toString();
} catch (Exception e) {
return null;
}
}
public Uri insert(Uri uri, ContentValues values) {
return null;
}
public boolean onCreate() {
return true;
}
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
static {
uriMatcher.addURI(".fontcontentprovider", "fonts", 1);
}
}
答案 0 :(得分:2)
TL; DR:要创建FlipFont,您需要在资产中使用有效的字体文件和XML文件。 APK需要使用Monotype的私钥存储区签名,这是不可能的。
三星和其他制造商使用Monotype的FlipFont来更改没有root的系统字体。三星和Monotype Imaging Inc.希望您付费更换字体,并且已经齐心协力阻止安装免费字体。
您不需要任何代码来为FlipFont创建字体,因此您可以删除FontContentProvider.java
。
要创建适用于FlipFont的APK,您需要以下3件事:
1) assets/fonts/ReplaceWithFontName.ttf
2) assets/xml/ReplaceWithFontName.xml
3)使用Monotype的私有密钥库构建并签署应用程序。
资产的示例XML:
<?xml version="1.0" encoding="utf-8"?>
<font displayname="ReplaceWithFontName">
<sans>
<file>
<filename>ReplaceWithFontName.ttf</filename>
<droidname>DroidSans.ttf</droidname>
</file>
<file>
<filename>ReplaceWithFontName.ttf</filename>
<droidname>DroidSans-Bold.ttf</droidname>
</file>
</sans>
</font>
现在,再看看#3。您需要使用Monotype的密钥库对APK进行签名。您无权访问此内容。因此,您的APK无法在三星设备上运行。
以下方法是从Samsung设备上的“设置”应用程序中反编译的,用于检查FlipFont APK是否使用正确的密钥签名:
protected boolean checkFont(String apkname) {
if (DEBUG) {
Log.secD("FlipFont", "checkFont - checking apkname" + apkname);
}
if ("com.monotype.android.font.foundation".equals(apkname)) {
return false;
}
PackageManager pm = this.mContext.getPackageManager();
for (int i = 0; i < apkNameList.length; i++) {
if (apkname != null) {
if (apkname.equals(apkNameList[i])) {
this.isCheckPlatformSignatures = pm.checkSignatures("android", apkNameList[i]) == 0;
this.isCheckReleaseSignatures = Utils.isSignatureMatch(this.mContext, apkNameList[i]);
Log.i("FontPreviewTablet", "apkname : " + apkname + ", isCheckPlatformSignatures : " + this.isCheckPlatformSignatures + ", isCheckReleaseSignatures : " + this.isCheckReleaseSignatures);
if (!(this.isCheckPlatformSignatures || this.isCheckReleaseSignatures)) {
if (apkname.equals("")) {
}
}
return false;
}
continue;
}
}
if (DEBUG) {
Log.secD("FlipFont", "checkFont - check if valid certificate");
}
PackageInfo packageInfo = null;
try {
packageInfo = this.mFontListAdapter.mPackageManager.getPackageInfo(apkname, 64);
} catch (Exception e) {
}
if (packageInfo != null) {
Signature[] signatures = packageInfo.signatures;
byte[] cert = signatures[0].toByteArray();
try {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signatures[0].toByteArray());
if ("T84drf8v3ZMOLvt2SFG/K7ODXgI=".equals(Base64.encodeToString(md.digest(), 0).trim())) {
if (DEBUG) {
Log.v("FlipFont", "**Signature is correct**");
}
return false;
}
if (DEBUG) {
Log.v("FlipFont", "**Signature is incorrect**");
}
return true;
} catch (Exception e2) {
e2.printStackTrace();
InputStream input = new ByteArrayInputStream(cert);
CertificateFactory cf = null;
try {
cf = CertificateFactory.getInstance("X509");
} catch (CertificateException e3) {
e3.printStackTrace();
}
X509Certificate c = null;
try {
c = (X509Certificate) cf.generateCertificate(input);
} catch (CertificateException e32) {
e32.printStackTrace();
}
if (DEBUG) {
Log.secD("Example", "APK name: " + apkname);
if (c != null) {
Log.secD("Example", "Certificate for: " + c.getSubjectDN());
Log.secD("Example", "Certificate issued by: " + c.getIssuerDN());
Log.secD("Example", "The certificate is valid from " + c.getNotBefore() + " to " + c.getNotAfter());
Log.secD("Example", "Certificate SN# " + c.getSerialNumber());
Log.secD("Example", "Generated with " + c.getSigAlgName());
}
}
String certIssuedByString = "CN=Ed Platz, OU=Display Imaging, O=Monotype Imanging Inc., L=Woburn, ST=MA, C=US";
if (c != null && certIssuedByString.equals(c.getIssuerDN().toString())) {
if (DEBUG) {
Log.secD("FlipFont", "**Certificate data is correct**");
}
return false;
}
}
}
return true;
}
如果您查看上述方法,您会注意到如果APK的包名称为“com.monotype.android.font.foundation”,则不会检查APK签名。
答案 1 :(得分:1)
我不确定是否可以在没有root的情况下更改系统字体类型,但您可以更改系统字体比例。您应该使用FONT_SCALE字符串和浮点值。下面是一个示例代码段。
Settings.System.putFloat(getBaseContext().getContentResolver(),
Settings.System.FONT_SCALE, (float) 1.0);
请注意,您应该为Android清单文件添加必要的WRITE_SETTINGS权限。
您可以找到文档的其余部分here