Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android N: PrintManager.print() results in java.lang.IllegalStateException: Can print only from an activity

My app is using PDF printing using PrintManager. This functionality is running just fine in Android L and M but fails under Android N.

Print action is called within a non-fragment activity from options menu in onOptionsItemSelected().

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
    String jobName = "createPDFReport";
    printManager.print(jobName, new InterimReportAdapter(AuditValidation.this, auditObject), new PrintAttributes.Builder().build());
}

Android N throws

FATAL EXCEPTION: ec.kat.kataudit, PID: 4052
java.lang.IllegalStateException: Can print only from an activity
at android.print.PrintManager.print(PrintManager.java:525)
at ec.kat.kataudit.AuditValidation.onOptionsItemSelected(AuditValidation.java:124)
at android.app.Activity.onMenuItemSelected(Activity.java:3204)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:408)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
...

AuditValidation.java:124 is pointing to printManager.print() call.

Activity extends android.support.v7.app.AppCompatActivity. Compile target version is 25, app is using latest libraries (25.3.1 as of today).

Any ideas are very much appreciated!

Best regards!

like image 230
ClausS Avatar asked Apr 28 '17 13:04

ClausS


1 Answers

Problem found. In attachBaseContext() of my activity I have a language swap implemented, which has Android N create a new context by createConfigurationContext(). This obviously voids the reference PrintManager instance is using, resulting in above IllegalStateException. I will now have to find a workaround for this.

EDIT: My solution is to store a reference of the original Context passed to attachBaseContext() in a member of my activity. PrintManager instance then is retrieve by invoking getSystemService() on the original Context reference, not the than active one.

private Context primaryBaseActivity;//THIS WILL KEEP ORIGINAL INSTANCE

@Override
protected void attachBaseContext(Context newBase) {
    primaryBaseActivity=newBase;//SAVE ORIGINAL INSTANCE

    /*Some locale handling stuff right here*/
    /*LocaleHelper's onAttach is returning a *new* context in Android N which will void PrintManager's context*/
    super.attachBaseContext(LocaleHelper.onAttach(newBase,appLocale));

}

When starting printing (PDF generation):

PrintManager printManager = (PrintManager) primaryBaseActivity.getSystemService(Context.PRINT_SERVICE);
like image 187
ClausS Avatar answered Sep 27 '22 17:09

ClausS