简体   繁体   中英

How to create view in background service to save the canvas as a picture?

This might be an strange requirement, however, it is useful in specific cases. Eg when you running a web service on an Android device and serves the page with special drawings.

All the web service stuff will be running in a background thread in a background service, without any visible activity widows. How can I inflate the some layout file into a view and change the content in Java in the background thread?

Is that possible? How?

public class MyIntentService extends IntentService {
    @Override
    protected void onHandleIntent(Intent intent) {
        LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
        View view = inflater.inflate(R.layout.view, null);
        Button button = (Button) view.findViewById( R.id.button );

        String text = intent.getExtras().getString("text");
        button.setText(text);

        view.setDrawingCacheEnabled(true);
        Bitmap bitmap = view.getDrawingCache();
    }
}

As I'm uncertain of the exact use case, the following code is merely proof of concept, but should be easily adapted to your needs. A sample layout is inflated in an IntentService, various View attributes are altered, and a Bitmap is saved to external storage.

The layout file, off_screen.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linear_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:background="#aaddff" >

    <ImageView android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher" />

    <TextView android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#000000"
        android:text="Hello!" />

</LinearLayout>

The IntentService class, ViewPictureService :

public class ViewPictureService extends IntentService
{   
    public static final String EXTRA_WIDTH = "width";
    public static final String EXTRA_HEIGHT = "height";
    public static final String EXTRA_RESOURCE = "resource";
    public static final String EXTRA_FILENAME = "filename";

    public ViewPictureService()
    {
        super("ViewPictureService");
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        int resId = intent.getIntExtra(EXTRA_RESOURCE, 0);
        int width = intent.getIntExtra(EXTRA_WIDTH, -1);
        int height = intent.getIntExtra(EXTRA_HEIGHT, -1);
        String filename = intent.getStringExtra(EXTRA_FILENAME);

        saveLayoutBitmap(resId, width, height, filename);
    }

    private void saveLayoutBitmap(int resId, int width, int height, String filename)
    {
        LayoutInflater inflater = LayoutInflater.from(this);
        View view = inflater.inflate(resId, null);

        ((LinearLayout) view).setBackgroundColor(Color.RED);
        ((TextView) view.findViewById(R.id.text_view)).setText("World!");
        ((ImageView) view.findViewById(R.id.image_view)).setImageDrawable(getResources().getDrawable(android.R.drawable.ic_dialog_alert));

        WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();

        int w = width < 0 ? display.getWidth() : width;
        int h = height < 0 ? display.getHeight() : height;

        view.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), 
                     MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));

        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();

        String target = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
            + File.separator + filename;
        File f = new File(target);

        try
        {
            FileOutputStream fos = new FileOutputStream(f);
            bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.flush();
            fos.close();
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }       
    }
}

And a sample invocation of the Service:

Intent intent = new Intent(this, ViewPictureService.class);

intent.putExtra(ViewPictureService.EXTRA_RESOURCE, R.layout.off_screen);
intent.putExtra(ViewPictureService.EXTRA_WIDTH, 540);
intent.putExtra(ViewPictureService.EXTRA_HEIGHT, 960);
intent.putExtra(ViewPictureService.EXTRA_FILENAME, "view_" + System.currentTimeMillis() + ".png");

startService(intent);

Of course, the file write will need a permission in the manifest:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

And the Service will need an entry in the <application> section:

<service android:name=".ViewPictureService" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM