【问题标题】:How to make app that can change Android user interface font?如何制作可以更改Android用户界面字体的应用程序?
【发布时间】:2018-03-24 14:24:02
【问题描述】:

我想知道是否有人知道如何创建一个可以更改三星手机界面字体样式的应用程序。我有我最喜欢的 TrueType 格式的字体样式。

Galaxy Apps 商店中有很多字体样式,但它们是付费的,而不是我想要的。您可以以this app 为例,安装后用户可以转到设置>设备>字体样式>从列表中选择字体并更改字体样式。

我试过反编译它,但没有得到太多。或者换句话说,翻转字体应用程序。

反编译源码

<?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);
    }
}

我尝试将它放在我的应用程序中,但它不起作用。

【问题讨论】:

  • 您可以更改操作系统字体大小,但不确定字体。!
  • 为什么不把字体样式放在资源中,就像这个例子一样?很好理解……alvinalexander.com/android/…

标签: java android fonts interface font-style


【解决方案1】:

虽然原生 Android 缺乏自定义系统字体的能力, 许多制造商已经调整了他们的软件来支持这一点 高度要求的功能,允许您轻松更改字体 安卓

Source

这意味着没有可以插入的系统 API 使字体在所有 Android 设备上都可以使用。但是,个别制造商确实提供了自定义字体实现。

我快速搜索了您,但似乎这些制造商不提供官方/通用 API(或像 Samsung 这样模糊的 API)来更改字体,相反,您必须查看每个制造商单独实现主题/字体(逆向工程?),并了解如何设置系统范围的字体以及如何插入该系统。

如果您正在寻找根应用程序如何执行此操作的示例,有许多可以操作字体的开源应用程序,like this

【讨论】:

  • 在在这里提问之前等待很长时间后非常感谢的答案我做了很多在线搜索但找不到任何答案但是如果你查看应用程序(有问题的链接)你只需安装它然后您可以轻松地从设置中更改字体,我认为必须有一种方法,否则该应用程序将无法运行我不希望我的应用程序用户强行 root 他们的手机我知道他们不会使用它
  • @DreamDeveloper 别误会,使用制造商特定的 API 可以更改 一些 设备上的主题。例如。您所指的应用声明“支持的设备:三星 Galaxy 设备”
  • 你是对的,但我的第一个目标是 mi 的 Galaxy 设备我做了一个主题,但对于 Galaxy 设备我需要制作这个应用程序并且非常快
【解决方案2】:

我猜你不能这样做,除非你需要root你的手机,因为三星不允许你从应用程序更改字体它需要root permission,但我不确定!

【讨论】:

  • 我在上面的问题中给出了应用程序不需要root权限的链接
【解决方案3】:

我/您需要使用 Monotype 的密钥库对 APK 进行签名。我/您无权访问此内容。因此,您的 APK 将无法在三星设备上运行。 以下方法是从三星设备上的设置应用程序中反编译的,用于检查 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 签名。

【讨论】:

    猜你喜欢
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2013-11-06
    • 1970-01-01
    • 2016-05-08
    • 2020-10-20
    相关资源
    最近更新 更多