Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve permission model #5

Merged
merged 3 commits into from
Oct 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,9 @@ A few notes:
- For text, please use `DocumentTextView`: it will notify the parent when it gets bigger.
- For editable text, please use `DocumentEditText`: same as above.
- If using app compat, you might want to use the `AppCompat-` version of these widgets.
- We can't split text of a single view into multiple pages or columns.
- We can't split text of a single view into multiple pages or columns (for now).
It is your responsibility to have Views that are small enough to avoid blank spaces.
- For custom views, take a look at `DocumentHelper` methods.

To enable columns, use `document.setColumnsPerPage(int)` or the XML attribute `app:columnsPerPage`.

Expand Down Expand Up @@ -230,7 +231,10 @@ You must have appropriate permissions to write the file in that location.
On Marshmallow+, these permissions must be explicitly asked to the user.

The library currently will automatically ask the `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE`
permissions (this can be improved though). Make sure you implement `onRequestPermissionResult`:
permissions if the output file appears to be in the external storage. Make sure you

- declare these permissions in your manifest
- implement `onRequestPermissionResult` as such:

```java
@Override
Expand Down
3 changes: 3 additions & 0 deletions demo/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<manifest package="com.otaliastudios.printer.demo"
xmlns:android="http://schemas.android.com/apk/res/android">

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

<application
android:allowBackup="true"
android:icon="@drawable/logo_48dp"
Expand Down
3 changes: 0 additions & 3 deletions library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
package="com.otaliastudios.printer"
xmlns:android="http://schemas.android.com/apk/res/android">

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

<application
android:allowBackup="true"
android:supportsRtl="true"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ public void setPrintScale(int maxWidth, int maxHeight) {
@Override
public void print(final String printId, @NonNull final File directory, @NonNull String filename) {
Context context = mDocument.getContext();
if (!checkPermission(context)) return;
if (!checkPermission(context, directory)) return;
if (!checkPreview(printId, directory, filename)) return;

if (filename.toLowerCase().endsWith(mFormat)) {
filename = filename.substring(0, filename.length() - 4);
filename = filename.substring(0, filename.length() - mFormat.length());
}
if (mDocument.getPageCount() == 0) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,8 @@ interface Container<Root extends Container, Child extends Container> {
* - check if {@code child} can get some views from the next child
*
* @param child the container notifying us
* @param space the available space
*/
void onSpaceAvailable(Child child, int space);
void onSpaceAvailable(Child child);

/**
* Our child notifies that he has no more space, and some of the views would actually
Expand Down
24 changes: 12 additions & 12 deletions library/src/main/java/com/otaliastudios/printer/DocumentColumn.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class DocumentColumn extends LinearLayout implements Container<DocumentPage, Doc

private int mWidthBound;
private int mHeightBound;
private int mAvailableSpace;
private int mContentHeight;
private int mColumnNumber;

DocumentColumn(@NonNull Context context, int number, int widthBound, int heightBound) {
Expand All @@ -49,7 +49,6 @@ int getNumber() {
void setBounds(int widthBound, int heightBound) {
mWidthBound = widthBound;
mHeightBound = heightBound;
mAvailableSpace = mHeightBound;
}

boolean isBounded() {
Expand Down Expand Up @@ -88,7 +87,7 @@ public boolean contains(View view) {
}

@Override
public void onSpaceAvailable(DocumentColumn child, int space) {
public void onSpaceAvailable(DocumentColumn child) {
// We have no children so no one can call this.
}

Expand Down Expand Up @@ -201,31 +200,32 @@ private int getCurrentHeight() {
/**
* Something changed here.
* - did it grow? Do nothing. Due to measuring, we don't let anyone grow beyond the page size.
* - did it shrink and is the first? See if previous child wants it.
* - did it shrink? See if we should accept a view from the next child.
* - did it shrink? Notify we have space available.
*/
@Override
public void onLayoutChange(View view, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
int oldHeight = oldBottom - oldTop;
int newHeight = bottom - top;
mAvailableSpace = mHeightBound - newHeight;
// Our LayoutParams have a fixed height, see DocumentPage.
// So we are not going to grasp anything meaningful from bottom - top.
int oldHeight = mContentHeight;
int newHeight = getCurrentHeight();
int space = mHeightBound - newHeight;
final int pn = getRoot().getNumber();
mLog.v("onLayoutChange:", "page:", pn, "oldHeight:", oldHeight, "newHeight:", newHeight, "avSpace:", mAvailableSpace);
mLog.v("onLayoutChange:", "page:", pn, "oldHeight:", oldHeight, "newHeight:", newHeight, "space:", space);

mContentHeight = newHeight;
if (oldHeight == 0) return; // First pass.
if (newHeight == oldHeight) return; // Not really changed. This happens.
if (newHeight > oldHeight) return; // Nothing to do, hope we get calls to notifyTooSmall.
if (mAvailableSpace <= 0) return;
if (space <= 0) return;

// Go out of the layout pass, it's not safe to pass views around during layout,
// even if you use addViewInLayout or removeViewInLayout.
final int availableSpace = mAvailableSpace;
post(new Runnable() {
@Override
public void run() {
mLog.i("onLayoutChange:", "page:", pn, "dispatching onSpaceAvailable.");
getRoot().onSpaceAvailable(DocumentColumn.this, availableSpace);
getRoot().onSpaceAvailable(DocumentColumn.this);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,42 @@
import com.otaliastudios.printer.view.DocumentTextView;

/**
* Static utilities for text containers that might become smaller than they would like to,
* without notifying the parent.
* Static utilities for views that might become smaller than they would like to,
* without notifying the parent. In that case we want to move them to the next page, for example.
*
* It is recommended that they call {@link #onLayout(View)} here to have our splitting
* policy working.
* It is recommended that these views call {@link #onLayout(View)} to let us determine if they would
* like to be bigger, or {@link #onSpaceOver(View)} if they have already determined that.
*
* @see DocumentTextView
* @see DocumentEditText
*/
public class DocumentTextHelper {
public class DocumentHelper {

private final static String TAG = DocumentTextHelper.class.getSimpleName();
private final static String TAG = DocumentHelper.class.getSimpleName();
private final static PrinterLogger LOG = PrinterLogger.create(TAG);

/**
* To be called after the View has been laid out. If the view is presumably to small,
* this will call {@link #onSpaceOver(View)} for you.
*
* @param view The view that has been laid out
*/
public static void onLayout(View view) {
if (view.getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
LOG.i("onLayout:", "We are wrap content. Looking if we can scroll.");
// TODO: don't do this if getMaxLines is >= 0 (< MAX_VALUE). Same for getMaxheight.
if (view.canScrollVertically(-1) || view.canScrollVertically(1)) {
LOG.w("onLayout:", "We can scroll. Notifying the parent column.");
notifyContainer(view);
onSpaceOver(view);
}
}
}

private static void notifyContainer(View view) {
/**
* Notifies the {@link DocumentView} that this view would like to be bigger than
* it actually is. This might trigger a re-layout, for example moving the view to the
* next page.
*
* @param view The view that would like to be bigger
*/
public static void onSpaceOver(View view) {
Container<?, ?> container = null;
View current = view;
while (true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public boolean contains(View view) {
}

@Override
public void onSpaceAvailable(DocumentColumn child, int space) {
public void onSpaceAvailable(DocumentColumn child) {
Utils.clearUntakableView(child);
mLog.i("onSpaceAvailable:", "fromColumn:", child.getNumber());

Expand All @@ -286,9 +286,7 @@ public void onSpaceAvailable(DocumentColumn child, int space) {
DocumentColumn next = mColumns.get(which + 1);
while (tryPassFirstViewToPrevious(next, child)) {} // try until it stops
} else {
// TODO: the 'space' value at this point might not be meaningful
// (might be bigger if we gave something to previous column). But it's unused
getRoot().onSpaceAvailable(this, space);
getRoot().onSpaceAvailable(this);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public boolean contains(View view) {
}

@Override
public void onSpaceAvailable(DocumentPage child, int space) {
public void onSpaceAvailable(DocumentPage child) {
Utils.clearUntakableView(child);
LOG.i("onSpaceAvailable:", "fromPage:", child.getNumber());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public PdfPrinter(@NonNull DocumentView document, @NonNull PrintCallback callbac
@Override
public void print(final String printId, @NonNull final File directory, @NonNull String filename) {
Context context = mDocument.getContext();
if (!checkPermission(context)) return;
if (!checkPermission(context, directory)) return;
if (!checkPreview(printId, directory, filename)) return;
if (!filename.toLowerCase().endsWith(".pdf")) filename += ".pdf";
final File file = new File(directory, filename);
Expand Down
15 changes: 14 additions & 1 deletion library/src/main/java/com/otaliastudios/printer/Printer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.view.ViewTreeObserver;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
* A general interface for engines that can print view hierarchies to some sort or file or folder.
Expand Down Expand Up @@ -57,7 +61,16 @@ public void onGlobalLayout() {
return true;
}

boolean checkPermission(Context context) {
boolean checkPermission(Context context, File directory) {
// Check external permissions... But only if the directory is external.
// For external dirs, this still implies that the developers add the permissions to their manifest.

// Could be better, but anyway..
File ext = Environment.getExternalStorageDirectory();
if (!directory.getAbsolutePath().startsWith(ext.getAbsolutePath())) {
return true; // Not external
}

if (Build.VERSION.SDK_INT < 23) return true;

String[] permissions = new String[2];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;

import com.otaliastudios.printer.DocumentTextHelper;
import com.otaliastudios.printer.DocumentHelper;
import com.otaliastudios.printer.DocumentView;

/**
Expand All @@ -15,7 +15,7 @@
* Don't use if you don't have appcompat in your classpath.
*
* @see AppCompatDocumentTextView
* @see DocumentTextHelper
* @see DocumentHelper
*/
public class AppCompatDocumentEditText extends AppCompatEditText {

Expand All @@ -34,6 +34,6 @@ public AppCompatDocumentEditText(Context context, @Nullable AttributeSet attrs,
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
DocumentTextHelper.onLayout(this);
DocumentHelper.onLayout(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;

import com.otaliastudios.printer.DocumentTextHelper;
import com.otaliastudios.printer.DocumentHelper;
import com.otaliastudios.printer.DocumentView;
import com.otaliastudios.printer.view.AppCompatDocumentEditText;

/**
* A {@link android.support.v7.widget.AppCompatTextView} implementation that works well when
* laid out inside a {@link DocumentView}.
* Don't use if you don't have appcompat in your classpath.
*
* @see AppCompatDocumentEditText
* @see DocumentTextHelper
* @see DocumentHelper
*/
public class AppCompatDocumentTextView extends AppCompatTextView {

Expand All @@ -35,6 +34,6 @@ public AppCompatDocumentTextView(Context context, @Nullable AttributeSet attrs,
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
DocumentTextHelper.onLayout(this);
DocumentHelper.onLayout(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
import android.util.AttributeSet;
import android.widget.EditText;

import com.otaliastudios.printer.DocumentTextHelper;
import com.otaliastudios.printer.DocumentHelper;
import com.otaliastudios.printer.DocumentView;
import com.otaliastudios.printer.view.DocumentTextView;

/**
* An {@link EditText} implementation that works well when laid out inside
* a {@link DocumentView}.
*
* @see DocumentTextView
* @see DocumentTextHelper
* @see DocumentHelper
*/
@SuppressLint("AppCompatCustomView")
public class DocumentEditText extends EditText {
Expand All @@ -42,6 +41,6 @@ public DocumentEditText(Context context, @Nullable AttributeSet attrs, int defSt
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
DocumentTextHelper.onLayout(this);
DocumentHelper.onLayout(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
import android.util.AttributeSet;
import android.widget.TextView;

import com.otaliastudios.printer.DocumentTextHelper;
import com.otaliastudios.printer.DocumentHelper;
import com.otaliastudios.printer.DocumentView;

/**
* A {@link TextView} implementation that works well when laid out inside
* a {@link DocumentView}.
*
* @see DocumentEditText
* @see DocumentTextHelper
* @see DocumentHelper
*/
@SuppressLint("AppCompatCustomView")
public class DocumentTextView extends TextView {
Expand All @@ -41,6 +41,6 @@ public DocumentTextView(Context context, @Nullable AttributeSet attrs, int defSt
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
DocumentTextHelper.onLayout(this);
DocumentHelper.onLayout(this);
}
}