Search code examples
javaandroidfilenexus-7

How to File Save (Screenshot) Locally in Java?


I'm nearing the end of an internship for app development and I was assigned to create an app from scratch, instead of porting the apple version. I am having trouble figuring out how to save an in app screenshot, and then saving it to the device. I do not want to save externally because you can't assume everyone uses an SD card.

Here is my code, when I hit send I want the screenshot generated and saved so that when I use my share intent I can send the screenshot.

import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.ShareActionProvider;
import android.support.v4.view.MenuItemCompat;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Toast;
import android.text.TextWatcher;
import android.text.Editable;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.content.Intent;
import android.content.Context;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class MainActivity extends ActionBarActivity {
TextView CodexTV;
EditText CodexET;

@Override
public class MainActivity extends ActionBarActivity {
TextView CodexTV;
EditText CodexET;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Loading our AvianKingdom Codex Font
    Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/WWAvianKingdom-Regular.ttf");
    //Text view label
    CodexET = ((EditText) findViewById(R.id.CodexMessage));
    //REAL-TIME Textview change
    CodexET.addTextChangedListener(new TextWatcher() {
        public void afterTextChanged(Editable s) {   //Convert the Text to String
            String inputText = CodexET.getText().toString();
            CodexTV = ((TextView) findViewById(R.id.CustomFontText));
            CodexTV.setText(inputText);
        }
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // TODO Auto-generated method stub
        }
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // TODO Auto-generated method stub
        }
    });

    //Applying the font
    CodexET.setTypeface(tf);

    //Screenshot our Codex'ed Image
    CodexET.setOnKeyListener(new OnKeyListener()
    {
        public boolean onKey(View v, int keyCode, KeyEvent event)
        {
            if (event.getAction() == KeyEvent.ACTION_DOWN)
            {
                switch (keyCode)
                {
                    case KeyEvent.KEYCODE_DPAD_CENTER:
                        doShare(getDefaultIntent());
                        captureScreen();
                    case KeyEvent.KEYCODE_ENTER:
                        doShare(getDefaultIntent());
                        captureScreen();
                    default:
                        break;
                }
            }
            return false;
        }
    });
}

// Basic Share Intent to handle Sharing through Applications.
private Intent getDefaultIntent()
{
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("image/*");
    return intent;
}

private ShareActionProvider mShareActionProvider;

Here is the function that gets called when users hit send:

 //Function for Screenshot and Saving picture.
public Bitmap captureScreen()
{   // Image naming and path.
    String fileName = "DR-Codex.jpg";

    // create bitmap screen capture
    Bitmap bitmap;
    View v1 = CodexET.getRootView();
    v1.setDrawingCacheEnabled(true);
    bitmap = Bitmap.createBitmap(v1.getDrawingCache());
    v1.setDrawingCacheEnabled(false);
    //Start writing to device.
    OutputStream fout = null;
    File imageFile;
    imageFile = new File(getExternalFilesDir(null), fileName);
    try
    {
        //Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
        //intent.setDataAndType(Uri.fromFile(new File(fileName)), "image/*");
        //startActivity(intent);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.JPEG, 90, bos);
        byte[] bitmapdata = bos.toByteArray();

        fout = new FileOutputStream(imageFile);
        fout.write(bitmapdata);
        fout.flush();
        Log.e("File saved yo", "but where");
        fout.close();
    }
    catch (FileNotFoundException e)
    {
        // TODO Auto-generated catch block
        Log.e("File Selector", "The selected file can't be shared: " + fileName);
        e.printStackTrace();
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        Log.e("File Selector", "The selected file can't be shared: " + fileName);
        e.printStackTrace();
    }
    finally {
        //Stuff
    }
    return bitmap;
}


private void doShare(Intent shareintent)
{
    mShareActionProvider.setShareIntent(shareintent);
    invalidateOptionsMenu();
}

It seems that with the Action.Create_Document intent I am able to create a blank file, but an image of my screen is still not generated.

Here is what the screen of the app looks like. Screenshot of App

And here is the most current report list, I believe I have highlighted the problem. DDMS Report


Solution

  • two things stand out to me ...

    1) add the .jpg extension to your filename. ie "DR-CODEX.jpg"

    2) don't save to private internal getFilesDir as then you will have problems sharing due to security. instead save to getExternalFilesDir(null)

    Edit

    also because of getExternalFilesDir, you will need the following in your AndroidManifest.xml

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

    and possibly

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