Search in sources :

Example 6 with Wrapper

use of com.codename1.util.Wrapper in project CodenameOne by codenameone.

the class Util method downloadUrlSafely.

/**
 * <p>
 * Safely download the given URL to the Storage or to the FileSystemStorage:
 * this method is resistant to network errors and capable of resume the
 * download as soon as network conditions allow and in a completely
 * transparent way for the user; note that in the global network error
 * handling, there must be an automatic
 * <pre>.retry()</pre>, as in the code example below.</p>
 * <p>
 * This method is useful if the server correctly returns Content-Length and
 * if it supports partial downloads: if not, it works like a normal
 * download.</p>
 * <p>
 * Pros: always allows you to complete downloads, even if very heavy (e.g.
 * 100MB), even if the connection is unstable (network errors) and even if
 * the app goes temporarily in the background (on some platforms the
 * download will continue in the background, on others it will be
 * temporarily suspended).</p>
 * <p>
 * Cons: since this method is based on splitting the download into small
 * parts (512kbytes is the default), this approach causes many GET requests
 * that slightly slow down the download and cause more traffic than normally
 * needed.</p>
 * <p>
 * Usage example:</p>
 * <script src="https://gist.github.com/jsfan3/554590a12c3102a3d77e17533e7eca98.js"></script>
 *
 * @param url
 * @param fileName must be a valid Storage file name or FileSystemStorage
 * file path
 * @param percentageCallback invoked (in EDT) during the download to notify
 * the progress (from 0 to 100); it can be null if you are not interested in
 * monitoring the progress
 * @param filesavedCallback invoked (in EDT) only when the download is
 * finished; if null, no action is taken
 * @throws IOException
 */
public static void downloadUrlSafely(String url, final String fileName, final OnComplete<Integer> percentageCallback, final OnComplete<String> filesavedCallback) throws IOException {
    // Code discussion here: https://stackoverflow.com/a/62137379/1277576
    String partialDownloadsDir = FileSystemStorage.getInstance().getAppHomePath() + FileSystemStorage.getInstance().getFileSystemSeparator() + "partialDownloads";
    if (!FileSystemStorage.getInstance().isDirectory(partialDownloadsDir)) {
        FileSystemStorage.getInstance().mkdir(partialDownloadsDir);
    }
    // do its best to be unique if there are parallel downloads
    final String uniqueId = url.hashCode() + "" + downloadUrlSafelyRandom.nextInt();
    final String partialDownloadPath = partialDownloadsDir + FileSystemStorage.getInstance().getFileSystemSeparator() + uniqueId;
    // as discussed here: https://stackoverflow.com/a/57984257
    final boolean isStorage = fileName.indexOf("/") < 0;
    // total expected download size, with a check partial download support
    final long fileSize = getFileSizeWithoutDownload(url, true);
    // 512 kbyte, size of each small download
    final int splittingSize = 512 * 1024;
    final Wrapper<Long> downloadedTotalBytes = new Wrapper<Long>(0l);
    final OutputStream out;
    if (isStorage) {
        // leave it open to append partial downloads
        out = Storage.getInstance().createOutputStream(fileName);
    } else {
        out = FileSystemStorage.getInstance().openOutputStream(fileName);
    }
    // Codename One thread that supports crash protection and similar Codename One features.
    final EasyThread mergeFilesThread = EasyThread.start("mergeFilesThread");
    final ConnectionRequest cr = new GZConnectionRequest();
    cr.setUrl(url);
    cr.setPost(false);
    if (fileSize > splittingSize) {
        // Which byte should the download start from?
        cr.addRequestHeader("Range", "bytes=0-" + splittingSize);
        cr.setDestinationFile(partialDownloadPath);
    } else {
        Util.cleanup(out);
        if (isStorage) {
            cr.setDestinationStorage(fileName);
        } else {
            cr.setDestinationFile(fileName);
        }
    }
    cr.addResponseListener(new ActionListener<NetworkEvent>() {

        @Override
        public void actionPerformed(NetworkEvent evt) {
            mergeFilesThread.run(new Runnable() {

                @Override
                public void run() {
                    try {
                        // We append the just saved partial download to the fileName, if it exists
                        if (FileSystemStorage.getInstance().exists(partialDownloadPath)) {
                            InputStream in = FileSystemStorage.getInstance().openInputStream(partialDownloadPath);
                            Util.copyNoClose(in, out, 8192);
                            Util.cleanup(in);
                            // before deleting the file, we check and update how much data we have actually downloaded
                            downloadedTotalBytes.set(downloadedTotalBytes.get() + FileSystemStorage.getInstance().getLength(partialDownloadPath));
                            FileSystemStorage.getInstance().delete(partialDownloadPath);
                        }
                        // Is the download finished?
                        if (downloadedTotalBytes.get() > fileSize) {
                            throw new IllegalStateException("More content has been downloaded than the file length, check the code.");
                        }
                        if (fileSize <= 0 || downloadedTotalBytes.get() == fileSize) {
                            // yes, download finished
                            Util.cleanup(out);
                            if (filesavedCallback != null) {
                                CN.callSerially(new Runnable() {

                                    @Override
                                    public void run() {
                                        filesavedCallback.completed(fileName);
                                    }
                                });
                            }
                        } else {
                            // no, it's not finished, we repeat the request after updating the "Range" header
                            cr.addRequestHeader("Range", "bytes=" + downloadedTotalBytes.get() + "-" + (Math.min(downloadedTotalBytes.get() + splittingSize, fileSize)));
                            NetworkManager.getInstance().addToQueue(cr);
                        }
                    } catch (IOException ex) {
                        Log.p("Error in appending splitted file to output file", Log.ERROR);
                        Log.e(ex);
                        Log.sendLogAsync();
                    }
                }
            });
        }
    });
    NetworkManager.getInstance().addToQueue(cr);
    NetworkManager.getInstance().addProgressListener(new ActionListener<NetworkEvent>() {

        @Override
        public void actionPerformed(NetworkEvent evt) {
            if (cr == evt.getConnectionRequest() && fileSize > 0) {
                // the following casting to long is necessary when the file is bigger than 21MB, otherwise the result of the calculation is wrong
                if (percentageCallback != null) {
                    CN.callSerially(new Runnable() {

                        @Override
                        public void run() {
                            percentageCallback.completed((int) ((long) downloadedTotalBytes.get() * 100 / fileSize));
                        }
                    });
                }
            }
        }
    });
}
Also used : Wrapper(com.codename1.util.Wrapper) DataInputStream(java.io.DataInputStream) InputStream(java.io.InputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) DataOutputStream(java.io.DataOutputStream) OutputStream(java.io.OutputStream) IOException(java.io.IOException) GZConnectionRequest(com.codename1.io.gzip.GZConnectionRequest) GZConnectionRequest(com.codename1.io.gzip.GZConnectionRequest) EasyThread(com.codename1.util.EasyThread)

Example 7 with Wrapper

use of com.codename1.util.Wrapper in project CodenameOne by codenameone.

the class MigLayout method checkCache.

/**
 * Check if something has changed and if so recreate it to the cached
 * objects.
 *
 * @param parent The parent that is the target for this layout manager.
 */
private void checkCache(Container parent) {
    if (parent == null) {
        return;
    }
    if (dirty) {
        grid = null;
    }
    cleanConstraintMaps(parent);
    // Check if the grid is valid
    int mc = PlatformDefaults.getModCount();
    if (lastModCount != mc) {
        grid = null;
        lastModCount = mc;
    }
    // if (!parent.isValid()) {
    if (!lastWasInvalid) {
        lastWasInvalid = true;
        int hash = 0;
        // Added in 3.7.3 to resolve a timing regression introduced in 3.7.1
        boolean resetLastInvalidOnParent = false;
        for (ComponentWrapper wrapper : ccMap.keySet()) {
            Object component = wrapper.getComponent();
            if (component instanceof TextArea) {
                resetLastInvalidOnParent = true;
            }
            hash ^= wrapper.getLayoutHashCode();
            hash += 285134905;
        }
        if (resetLastInvalidOnParent) {
            resetLastInvalidOnParent(parent);
        }
        if (hash != lastHash) {
            grid = null;
            lastHash = hash;
        }
        Dimension ps = new Dimension(parent.getWidth(), parent.getHeight());
        if (lastInvalidSize == null || !lastInvalidSize.equals(ps)) {
            grid = null;
            lastInvalidSize = ps;
        }
    }
    /*} else {
         lastWasInvalid = false;
         }*/
    ContainerWrapper par = checkParent(parent);
    setDebug(par, getDebugMillis() > 0);
    if (grid == null) {
        grid = new Grid(par, lc, rowSpecs, colSpecs, ccMap, callbackList);
    }
    dirty = false;
}
Also used : TextArea(com.codename1.ui.TextArea) Grid(com.codename1.ui.layouts.mig.Grid) Dimension(com.codename1.ui.geom.Dimension) ContainerWrapper(com.codename1.ui.layouts.mig.ContainerWrapper) ComponentWrapper(com.codename1.ui.layouts.mig.ComponentWrapper)

Example 8 with Wrapper

use of com.codename1.util.Wrapper in project CodenameOne by codenameone.

the class AndroidImplementation method addActionsToNotification.

/**
 * Adds actions to a push notification.  This is called by the Push broadcast receiver probably before
 * Codename One is initialized
 * @param provider Reference to the app's main class which implements PushActionsProvider
 * @param categoryId The category ID of the push notification.
 * @param builder The builder for the push notification.
 * @param targetIntent The target intent... this should go to the app's main Activity.
 * @param context The current context (inside the Broadcast receiver).
 * @throws IOException
 */
public static void addActionsToNotification(PushActionsProvider provider, String categoryId, NotificationCompat.Builder builder, Intent targetIntent, Context context) throws IOException {
    // NOTE:  THis will likely run when the main activity isn't running so we won't have
    // access to any display properties... just native Android APIs will be accessible.
    PushActionCategory category = null;
    PushActionCategory[] categories;
    if (provider != null) {
        categories = provider.getPushActionCategories();
    } else {
        categories = getInstalledPushActionCategories(context);
    }
    for (PushActionCategory candidateCategory : categories) {
        if (categoryId.equals(candidateCategory.getId())) {
            category = candidateCategory;
            break;
        }
    }
    if (category == null) {
        return;
    }
    int requestCode = 1;
    for (PushAction action : category.getActions()) {
        Intent newIntent = (Intent) targetIntent.clone();
        newIntent.putExtra("pushActionId", action.getId());
        PendingIntent contentIntent = createPendingIntent(context, requestCode++, newIntent);
        try {
            int iconId = 0;
            try {
                iconId = Integer.parseInt(action.getIcon());
            } catch (Exception ex) {
            }
            // android.app.Notification.Action.Builder actionBuilder = new android.app.Notification.Action.Builder(iconId, action.getTitle(), contentIntent);
            System.out.println("Adding action " + action.getId() + ", " + action.getTitle() + ", icon=" + iconId);
            if (ActionWrapper.BuilderWrapper.isSupported()) {
                // We need to take this abstracted "wrapper" approach because the Action.Builder class, and RemoteInput class
                // aren't available until API 22.
                // These classes use reflection to provide support for these classes safely.
                ActionWrapper.BuilderWrapper actionBuilder = new ActionWrapper.BuilderWrapper(iconId, action.getTitle(), contentIntent);
                if (action.getTextInputPlaceholder() != null && RemoteInputWrapper.isSupported()) {
                    RemoteInputWrapper.BuilderWrapper remoteInputBuilder = new RemoteInputWrapper.BuilderWrapper(action.getId() + "$Result");
                    remoteInputBuilder.setLabel(action.getTextInputPlaceholder());
                    RemoteInputWrapper remoteInput = remoteInputBuilder.build();
                    actionBuilder.addRemoteInput(remoteInput);
                }
                ActionWrapper actionWrapper = actionBuilder.build();
                new NotificationCompatWrapper.BuilderWrapper(builder).addAction(actionWrapper);
            } else {
                builder.addAction(iconId, action.getTitle(), contentIntent);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
Also used : PushActionCategory(com.codename1.push.PushActionCategory) ActionWrapper(com.codename1.impl.android.compat.app.NotificationCompatWrapper.ActionWrapper) NotificationCompatWrapper(com.codename1.impl.android.compat.app.NotificationCompatWrapper) PushAction(com.codename1.push.PushAction) Paint(android.graphics.Paint) JSONException(org.json.JSONException) InvocationTargetException(java.lang.reflect.InvocationTargetException) RemoteException(android.os.RemoteException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) MediaException(com.codename1.media.AsyncMedia.MediaException) ParseException(java.text.ParseException) SAXException(org.xml.sax.SAXException) NameNotFoundException(android.content.pm.PackageManager.NameNotFoundException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) RemoteInputWrapper(com.codename1.impl.android.compat.app.RemoteInputWrapper)

Example 9 with Wrapper

use of com.codename1.util.Wrapper in project CodenameOne by codenameone.

the class AutoCompleteTextField method addPopup.

private void addPopup() {
    final Form f = getComponentForm();
    popup.removeAll();
    popup.setVisible(false);
    popup.setEnabled(false);
    filter(getText());
    final com.codename1.ui.List l = new com.codename1.ui.List(getSuggestionModel());
    if (getMinimumElementsShownInPopup() > 0) {
        l.setMinElementHeight(getMinimumElementsShownInPopup());
    }
    l.setScrollToSelected(false);
    l.setItemGap(0);
    for (ActionListener al : listeners) {
        l.addActionListener(al);
    }
    if (completionRenderer == null) {
        ((DefaultListCellRenderer<String>) l.getRenderer()).setShowNumbers(false);
    } else {
        l.setRenderer(completionRenderer);
    }
    l.setUIID("AutoCompleteList");
    l.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent evt) {
            pickedText = (String) l.getSelectedItem();
            setParentText(pickedText);
            fireActionEvent();
            // relaunch text editing if we are still editing
            if (Display.getInstance().isTextEditing(AutoCompleteTextField.this)) {
                Display.getInstance().editString(AutoCompleteTextField.this, getMaxSize(), getConstraint(), (String) l.getSelectedItem());
            }
            popup.setVisible(false);
            popup.setEnabled(false);
            f.repaint();
        }
    });
    byte[] units = popup.getStyle().getMarginUnit();
    if (units != null) {
        units[Component.LEFT] = Style.UNIT_TYPE_PIXELS;
        units[Component.TOP] = Style.UNIT_TYPE_PIXELS;
        popup.getAllStyles().setMarginUnit(units);
    }
    popup.getAllStyles().setMargin(LEFT, Math.max(0, getAbsoluteX()));
    int popupHeight = calcPopuupHeight(l);
    popup.setPreferredW(getWidth());
    popup.setHeight(popupHeight);
    popup.setWidth(getWidth());
    popup.addComponent(l);
    popup.layoutContainer();
    // block the reflow of this popup, which can cause painting problems
    dontCalcSize = true;
    if (f != null) {
        if (popup.getParent() == null) {
            Container lay = f.getLayeredPane(AutoCompleteTextField.this.getClass(), true);
            lay.setLayout(new LayeredLayout());
            Container wrapper = new Container();
            wrapper.add(popup);
            lay.addComponent(wrapper);
        }
        f.revalidate();
    }
}
Also used : ActionEvent(com.codename1.ui.events.ActionEvent) ActionListener(com.codename1.ui.events.ActionListener) ArrayList(java.util.ArrayList) LayeredLayout(com.codename1.ui.layouts.LayeredLayout)

Example 10 with Wrapper

use of com.codename1.util.Wrapper in project CodenameOne by codenameone.

the class AutoCompleteTextField method addPopup.

private void addPopup(boolean updateFilter) {
    final Form f = getComponentForm();
    popup.removeAll();
    popup.setVisible(false);
    popup.setEnabled(false);
    if (updateFilter) {
        filter(getText());
    }
    final com.codename1.ui.List l = new com.codename1.ui.List(getSuggestionModel());
    if (getMinimumElementsShownInPopup() > 0) {
        l.setMinElementHeight(getMinimumElementsShownInPopup());
    }
    l.setScrollToSelected(false);
    l.setItemGap(0);
    for (ActionListener al : listeners) {
        l.addActionListener(al);
    }
    if (completionRenderer == null) {
        ((DefaultListCellRenderer<String>) l.getRenderer()).setShowNumbers(false);
    } else {
        l.setRenderer(completionRenderer);
    }
    l.setUIID("AutoCompleteList");
    l.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent evt) {
            if (shouldShowPopup()) {
                pickedText = (String) l.getSelectedItem();
                setParentText(pickedText);
                fireActionEvent();
                // relaunch text editing if we are still editing
                if (Display.getInstance().isTextEditing(AutoCompleteTextField.this)) {
                    Display.getInstance().editString(AutoCompleteTextField.this, getMaxSize(), getConstraint(), (String) l.getSelectedItem());
                }
                popup.setVisible(false);
                popup.setEnabled(false);
                f.revalidate();
            }
        }
    });
    byte[] units = popup.getStyle().getMarginUnit();
    if (units != null) {
        units[Component.LEFT] = Style.UNIT_TYPE_PIXELS;
        units[Component.TOP] = Style.UNIT_TYPE_PIXELS;
        popup.getAllStyles().setMarginUnit(units);
    }
    int leftMargin = isRTL() ? Math.max(0, f.getWidth() - getAbsoluteX() - getWidth()) : Math.max(0, getAbsoluteX());
    popup.getAllStyles().setMargin(LEFT, leftMargin);
    int popupHeight = calcPopupHeight(l);
    popup.setPreferredW(getWidth());
    popup.setHeight(popupHeight);
    popup.setWidth(getWidth());
    popup.addComponent(l);
    popup.layoutContainer();
    // block the reflow of this popup, which can cause painting problems
    dontCalcSize = true;
    if (f != null) {
        if (popup.getParent() == null) {
            Container lay = f.getLayeredPane(AutoCompleteTextField.this.getClass(), true);
            lay.setLayout(new LayeredLayout());
            Container wrapper = new Container();
            wrapper.add(popup);
            lay.addComponent(wrapper);
        }
        f.revalidate();
    }
}
Also used : ActionEvent(com.codename1.ui.events.ActionEvent) ActionListener(com.codename1.ui.events.ActionListener) ArrayList(java.util.ArrayList) LayeredLayout(com.codename1.ui.layouts.LayeredLayout)

Aggregations

Container (com.codename1.ui.Container)9 BorderLayout (com.codename1.ui.layouts.BorderLayout)9 LayeredLayout (com.codename1.ui.layouts.LayeredLayout)6 IOException (java.io.IOException)6 Entity (com.codename1.rad.models.Entity)5 Form (com.codename1.ui.Form)5 ActionNode (com.codename1.rad.nodes.ActionNode)4 Label (com.codename1.ui.Label)4 Dimension (com.codename1.ui.geom.Dimension)4 ArrayList (java.util.ArrayList)4 EntityList (com.codename1.rad.models.EntityList)3 ActionEvent (com.codename1.ui.events.ActionEvent)3 ActionListener (com.codename1.ui.events.ActionListener)3 BoxLayout (com.codename1.ui.layouts.BoxLayout)3 UIManager (com.codename1.ui.plaf.UIManager)3 GZConnectionRequest (com.codename1.io.gzip.GZConnectionRequest)2 ControllerEvent (com.codename1.rad.controllers.ControllerEvent)2 EntityListProvider (com.codename1.rad.models.EntityListProvider)2 Button (com.codename1.ui.Button)2 Component (com.codename1.ui.Component)2