1

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

  • What exactly does this question have to do with Android Studio? It's just an IDE. – Squonk Apr 16 '15 at 18:56
  • Please don't put unnecessary tags on questions. It doesn't matter what your dev environment is if your app is failing to run on a device. Please only use tags for IDEs if your problem is related to build-time errors or when exporting APKs etc. – Squonk Apr 16 '15 at 19:10
  • No problem, removing tag. – Christian Jorge Lopez Apr 16 '15 at 19:22
  • See http://developer.android.com/training/secure-file-sharing/share-file.html – Chris Stratton Apr 17 '15 at 05:18
  • Thank you Chris for pointing me here, I don't understand completely what I need to implement into my project. – Christian Jorge Lopez Apr 21 '15 at 17:10
  • What is your exact problem? Does the file get created but blank or invalid? Or the file isn't even created where you intend? – DNax Apr 21 '15 at 17:21
  • The file doesn't seem to be created at all, I can't access it from the tablet. – Christian Jorge Lopez Apr 23 '15 at 15:48
  • 1
    Your file name generation code is horribly confused, incorporating the result of getCacheDir() *twice*, when you should not be using that result *at all* since it points to a location on the internal storage which is private to your app and not suitable for sharing. – Chris Stratton Apr 23 '15 at 20:00
  • getFilesDir() is not where you want to put this either. Use Environment.getExternalStorageDirectory() in conjunction with external storage permission, or use the newer APIs. See http://developer.android.com/training/basics/data-storage/files.html and avoid spaces in your file name too, as even if it may be accepted here it will cause you a problem somewhere. – Chris Stratton Apr 28 '15 at 15:58
  • The reason I wasn't using External was because this device I am testing on does not have a sd card. When I hit send, it begins the file creation and saves it, but it is a blank file with nothing in it. – Christian Jorge Lopez Apr 28 '15 at 16:27

1 Answers1

2

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" />
SteelBytes
  • 6,905
  • 1
  • 26
  • 28