-2

I want to make an app that can change system font style in galaxy phone after installing my app user can change font from Setting>my Device >font style and choose from list without requiring root permission. I have my own font style in true type file. Click here to see example of app I want to make.

Down Voting Won't help Please answer or dont vote down.

enter image description here

enter image description here

enter image description 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>

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);
    }
}
Dream Developer
  • 400
  • 5
  • 20

2 Answers2

2

TL;DR: To create a FlipFont you need a valid font file and XML file in assets. The APK needs to be signed with Monotype's private keystore, which isn't possible.


Samsung and other manufacturers use Monotype's FlipFont to change the system fonts without root. Samsung and Monotype Imaging Inc. want you to pay to change fonts and have made concerted efforts to block free fonts from being installed.

You don't need any code to create a font for FlipFont, so you can delete FontContentProvider.java.

To create an APK that works with FlipFont you need the following 3 things:

1) A valid font file in assets/fonts/ReplaceWithFontName.ttf

2) An XML in assets/xml/ReplaceWithFontName.xml

3) Build and sign the app with Monotype's private keystore.

Example XML for assets:

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

Now, look at #3 again. You need to sign the APK with Monotype's keystore. 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 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".

Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
1

I am not sure whether it is possible to change the system font type without rooting but you can change the system font scale. You should use FONT_SCALE string and a float value for this. An example code snippet is below.

Settings.System.putFloat(getBaseContext().getContentResolver(),
        Settings.System.FONT_SCALE, (float) 1.0);

Note that you should add the necessary WRITE_SETTINGS permission to your android manifest file.

You can find the rest of the documentation here

Fio
  • 3,088
  • 2
  • 13
  • 23
  • Well you can see in question I have given example if you have android phone you try to install it doesn't require root permission – Dream Developer Oct 30 '17 at 12:10
  • It seems there is an exception for a few devices including Samsung Galaxy devices about changing the system font without any root. Here is how you to do(same as rooted devices): 1) read the list of fonts and list them 2) change the system font as the user selects one from the list 3) If a custom font is to be set, store the desired font file under /system/font/ directory of Android device programmatically – Fio Oct 30 '17 at 13:35
  • yes agree although I have decompiled this app to get the code but as i am a beginner in coding i think if someone know coding they can help. there is only one activity in this app I will post code in question and etc – Dream Developer Oct 30 '17 at 15:04