Android N: PrintManager.print() results in java.la

2019-07-15 05:51发布

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!

3条回答
闹够了就滚
2楼-- · 2019-07-15 06:10

use this in your activity

private Context primaryBaseActivity;//THIS WILL KEEP ORIGINAL INSTANCE
@Override
protected void attachBaseContext(Context base) {
    primaryBaseActivity=base;
    super.attachBaseContext(base);
}

and replace this line

PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE); 

to

 PrintManager  printManager = (PrintManager) primaryBaseActivity.getSystemService(Context.PRINT_SERVICE);
查看更多
相关推荐>>
3楼-- · 2019-07-15 06:15

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);
查看更多
唯我独甜
4楼-- · 2019-07-15 06:24

you can try this :

public void printDocument(WebView webView, String title)
{
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
    {
        PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);

        //noinspection deprecation
        PrintDocumentAdapter printDocumentAdapter = webView.createPrintDocumentAdapter();

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) printDocumentAdapter = webView.createPrintDocumentAdapter(title);

        String documentName = mContext.getString(R.string.project_name)+" - "+title;

        PrintJob printJob = printManager.print(documentName, printDocumentAdapter, new PrintAttributes.Builder().build());

        List<PrintJob> printJobs = printManager.getPrintJobs();

        printJobs.add(printJob);
    }
    else
    {
        showToast(mContext.getString(R.string.mytools_printing_not_supported), 1);
    }
}
查看更多
登录 后发表回答