Как сделать приложение, которое может изменить шрифт интерфейса пользователя Android?
Я хочу знать, есть ли у кого-нибудь представление о том, как создать приложение, которое может изменить стиль шрифта интерфейса в телефонах Samsung. У меня есть мой любимый стиль шрифта со мной в формате TrueType.
В магазине Galaxy Apps есть много стилей шрифтов, но они платные, а не то, что я хочу. Вы можете увидеть это приложение в качестве примера того, что делает после установки, пользователь может просто перейти в "Настройки"> "Устройство"> "Стиль шрифта"> "Выбрать шрифт из списка" и изменить стиль шрифта.
Я пытался декомпилировать, но не получил много. Или, другими словами, приложение Flip Font.
Декомпилированный источник
<?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);
}
}
Я пытался вставить его в свое приложение, но оно не работает.
3 ответа
В то время как на складе Android отсутствует возможность настраивать системный шрифт, многие производители адаптировали свое программное обеспечение для поддержки этой крайне востребованной функции, позволяющей легко менять шрифты для Android.
Это означает, что нет системного API, который можно подключить, чтобы шрифты работали на всех устройствах Android. Тем не менее, отдельные производители предоставляют собственную реализацию шрифтов.
Я сделал быстрый поиск для вас, но, похоже, что эти производители не предоставляют официальных / обобщенных API (или нечетких, таких как Samsung) для изменения своих шрифтов, вместо этого вам придется рассматривать каждую тему / реализацию шрифтов каждого производителя отдельно. (обратный инжиниринг?), и узнайте, как установлены общесистемные шрифты и как вы можете подключиться к этой системе.
Если вы ищете пример того, как корневые приложения делают это, есть много приложений с открытым исходным кодом, которые манипулируют шрифтами, как это.
I/ Вам необходимо подписать APK с помощью хранилища ключей Monotype. Я / У вас нет доступа к этому. Следовательно, ваш APK не будет работать на устройствах Samsung. Следующий метод декомпилируется из приложения "Настройки" на устройстве 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 не проверяется, если APK имеет имя пакета "com.monotype.android.font.foundation".
Я думаю, что вы не можете сделать это, если вам не нужно рутировать свой телефон, потому что Samsung не позволяет вам менять шрифты из приложения, для которого требуется разрешение root, но я не уверен!