Skip to content

Commit

Permalink
Improve permission model (#5)
Browse files Browse the repository at this point in the history
* Rearrange permissions

* Fix wrap_content issues

* Update readme
  • Loading branch information
natario1 authored Oct 15, 2017
1 parent 346db2b commit 7b85c19
Show file tree
Hide file tree
Showing 15 changed files with 75 additions and 53 deletions.
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);
}
}

0 comments on commit 7b85c19

Please sign in to comment.