8

I want to know if anyone has any idea about how to create an app that can change the interface font style in Samsung phones. I have my favorite font style with me in TrueType format.

There are a lot of font style on Galaxy Apps store but they are paid and not what I want. You can see this app as an example what is does after installing the user can just go to Setting >Device >Font Style > Choose Font from List and change font style.

I have tried decompiling it but didn't get much of it. Or in other words, Flip Font app.

Decompiled source

<?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>

There is only one activity

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

I tried putting it in my app but it doesn't work.

halfer
  • 19,824
  • 17
  • 99
  • 186
Dream Developer
  • 400
  • 5
  • 20
  • You can change OS font size but not sure about fonts.! – Atif AbbAsi Oct 20 '17 at 07:09
  • why dont u put the font style in a resource just like this example? It's very understandable... https://alvinalexander.com/android/how-to-set-font-size-style-textview-programmatically – gumuruh Oct 21 '17 at 10:35

3 Answers3

2

While stock Android lacks the ability to customize your system font, plenty of manufacturers have adapted their software to support this highly requested feature, allowing you to easily change fonts for Android

Source

This means that there is no System API that you can plugin to make fonts work on all Android devices. However, individual manufactures do provide a custom font implementation.

I did a quick search for you, but it appears that these manufactures don't provide official/generalised APIs (or vague ones like Samsung) for changing their fonts, instead, you'd have to look at each manufactures theme/font implementation individually (reverse engineering?), and find out how system wide fonts are set and how you can plug into this system.

If you are looking for an example of how root apps do this, there are many open source apps that manipulate fonts, like this.

Community
  • 1
  • 1
Mdlc
  • 7,128
  • 12
  • 55
  • 98
  • much appreciated answer after long time waiting before asking question here I did alot of online search but couldn't find any answers but if you look at the app(link in question) that apk you just install it and then you can easily change font from setting, I think there must be a way otherwise that app wouldn't work I don't want my app users to force to root their phone I know they won't use it – Dream Developer Oct 20 '17 at 15:49
  • @DreamDeveloper Don't get me wrong, it is possible to change themes on **some** devices, using manufacturer specific APIs. For example. the app that you are referring to states "Supported devices: Samsung Galaxy devices" – Mdlc Oct 21 '17 at 12:21
  • you are right but my first target is galaxy devices for mi I made a theme but for galaxy devices I need to made this app and really quick – Dream Developer Oct 21 '17 at 12:27
0

I guess you cannot do it unless you need to root your phone, because samsung does not allow you to change fonts from an app it needs to have root permission but im not sure!

crafter
  • 53
  • 7
0

I/You need to sign the APK with Monotype's keystore. I/You don't have access to this. Therefore, your APK will not work on Samsung devices. The following method is decompiled from the Settings application on a Samsung device and is used to check if the FlipFont APK is signed with the correct key:

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

If I/you look at the above method you will notice that the APK signature isn't checked if the APK has a package name of "com.monotype.android.font.foundation".

Dream Developer
  • 400
  • 5
  • 20