Friday, October 5, 2018

Android: Last line of textview getting cut off / getting hide some parts of text view in LinearLayout

I have a horizontal LinearLayout containing a Checkbox followed by a TextView next to it. This LinearLayout is dynamically inflated multiple times in a fixed vertical LinearLayout contained within a RelativeLayout.
The problem is the last line of the TextView gets cut in half. This happens when the dynamic text is long and spans more than one row. Below is my xml portion which causing the problem:
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <CheckBox
        android:id="@+id/cbAllowTransferOnlyWifi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_gravity="fill"
        android:text="@string/transfer.over.wifi.only" />

</LinearLayout>
The solution is to appliy a LayoutGravity to the TextView item like below:
android:layout_gravity="fill"
And this is the fix.

Google Drive REST API V3 > Root listing > Google Drive REST API V3 Getting Root Folder Id > List of Files & Folders From Root Directory

My target to listing all files of 'My Drive', but only the files and folders which are immediately below, not all the ones in the Drive at once. It's easy with REST API V3, below is a full code snippet to get listing of files and folders from ROOT FOLDER

package com.pkm;

import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import sun.misc.BASE64Encoder;
import com.google.gson.Gson;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;

/**
 * Created by [PRITOM KUMAR] on 05-Oct-18.
 */
public class GoogleDriveRestApiV3 {
    public static void main(String[] args) throws Exception {
        /* I assumed you already have ACCESS TOKEN */
        String AUTH_TOKEN = "ya29.GlwtBm__";

        String FIELDS = "nextPageToken,files(id,name,mimeType,trashed,size,quotaBytesUsed)";
        String QUERY = URLEncoder.encode(
                "'root' in parents " +
                "and trashed = false",
                "UTF-8"
        );
        String URI = "https://www.googleapis.com/drive/v3/files?" +
                "fields=" + FIELDS + "&q=" + QUERY + "&access_token=" + AUTH_TOKEN;

        Map result = HttpJavaClient.doGet(URI);

        System.out.println(result);
        File outputFile = (File) result.get("outputFile");
        if (outputFile != null) {
            String output = "";
            List<String> lines = Files.readAllLines(outputFile.toPath(), Charset.defaultCharset());
            for (String line : lines) {
                output = output + line;
            }
            Gson gson = new Gson();
            Map data = gson.fromJson(output, Map.class);
            System.out.println(data);
            List<Map> files = (List<Map>) data.get("files");
            for (Map map : files) {
                System.out.println(map);
            }
        }
    }

    public static String base64Encode(byte[] data) {
        BASE64Encoder base64Encoder = new BASE64Encoder();
        return base64Encoder.encodeBuffer(data);
    }
}

class HttpJavaClient {
    public static enum Method {
        GET, POST, PUT, PATCH, DELETE
    }

    public static enum Type {
        XML, JSON, URL_ENCODED, HTTP;
    }

    public static Map doGet(String url) {
        return execute(url, Method.GET, "", Type.URL_ENCODED, null, null);
    }

    public static Map doPost(String url, String data, Type type, Map headers) {
        return execute(url, Method.POST, data, type, headers, null);
    }

    private static Map execute(String requestURL, Method requestMethod, String requestData, Type dataType, Map headers, Integer timeOutMilli) {
        String httpResponse = "", responseMessage = "";
        Integer httpCode = 0;
        timeOutMilli = timeOutMilli == null ? 1000 * 30 : timeOutMilli; /* Default read & write timeout */

        Map r = new HashMap();
        HttpsURLConnection connection = null;
        try {
            String contentType = "", accept = "", contentLength = "" + requestData.length();
            switch (dataType) {
                case XML:
                    contentType = "text/xml; charset=utf-8";
                    accept = "text/xml";
                    break;
                case JSON:
                    contentType = "application/json";
                    break;
                case URL_ENCODED:
                    contentType = "application/x-www-form-urlencoded";
                    break;
            }

            connection = (HttpsURLConnection) new URL(requestURL).openConnection();
            connection.setRequestMethod(requestMethod.name());
            connection.setConnectTimeout(timeOutMilli);
            connection.setReadTimeout(timeOutMilli);
            connection.setRequestProperty("Pragma", "no-cache");

            if (headers != null && headers.size() > 0) {
                for (Object name : headers.keySet().toArray()) {
                    if (name.toString().endsWith("tls")) {
                        //headers.put("tls", "TLSv1.2");
                        //headers.put("tls", "TLSv1");
                        SSLContext sc = SSLContext.getInstance(headers.get(name.toString()).toString());
                        sc.init(null, null, new java.security.SecureRandom());
                        connection.setSSLSocketFactory(sc.getSocketFactory());
                    }
                    else {
                        connection.setRequestProperty(name.toString(), headers.get(name.toString()).toString());
                    }
                }
            }

            if (requestData.length() > 0) {
                connection.setDoInput(true);
                connection.setDoOutput(true);

                if (accept.length() > 0) {
                    connection.setRequestProperty("Accept", accept);
                }
                if (contentType.length() > 0) {
                    connection.setRequestProperty("Content-Type", contentType);
                }

                connection.setRequestProperty("Content_length", contentLength);
                OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
                writer.write(requestData);
                writer.flush();
                writer.close();
            }

            httpCode = connection.getResponseCode();
            responseMessage = connection.getResponseMessage();

            if (httpCode >= 200 && httpCode <= 299) {
                String responseContentType = connection.getContentType();
                if (responseContentType == null || responseContentType.length() == 0) {
                    responseContentType = "txt";
                }
                else {
                    if (responseContentType.contains(";")) {
                        responseContentType = responseContentType.substring(0, responseContentType.indexOf(";"));
                    }
                    if (responseContentType.contains("text/html")) {
                        responseContentType = "html";
                    }
                    else if (responseContentType.contains("image/")) {
                        responseContentType = "image";
                    }
                    else if (responseContentType.contains("/")) {
                        String[] parts = responseContentType.split("/");
                        responseContentType = parts[parts.length - 1];
                    }
                }
                Map<String, List<String>> map = connection.getHeaderFields();
                for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                    System.out.println("Key=" + entry.getKey() + " ,Value=" + entry.getValue());
                }
                System.out.println("Key=ResponseType ,Value=" + responseContentType);

                File tempFile = File.createTempFile("hello", ".tmp");
                RandomAccessFile output = new RandomAccessFile(tempFile, "rw");

                InputStream is = connection.getInputStream();
                BufferedInputStream input = new BufferedInputStream(is);


                Integer fileLength = connection.getContentLength();
                int readSize = 1024, downloadedSize = 0;
                byte data[] = new byte[readSize];
                int count = 0;
                int progress = 0;

                Long timeNeeded = System.currentTimeMillis();
                while ((count = input.read(data, 0, readSize)) >= 0 && progress != 100)
                {
                    downloadedSize += count;
                    output.write(data, 0, count);
                    progress = (int) ((downloadedSize * 100) / fileLength);
                    Long mb = output.length() / (1024 * 1024);
                    System.out.println("PROGRESS = " + (progress) + "%, DOWNLOADED=" + mb + " MB, TYPE=" + responseContentType);
                }
                output.close();
                input.close();
                r.put("outputFile", tempFile);

                timeNeeded = (System.currentTimeMillis() - timeNeeded) / 1000;
                System.out.println("TIME REQUIRED=" + timeNeeded + " SECONDS!!!");
            }
        }
        catch (Exception ex) {
            httpResponse = "";
            responseMessage = ex.getMessage();
        }
        finally {
            try {
                connection.disconnect();
            }
            catch (Exception ex10) {
            }
        }
        r.put("code", httpCode);
        r.put("message", responseMessage);
        r.put("output", httpResponse);
        return r;
    }
}
Below is output of above example:

Key=null ,Value=[HTTP/1.1 200 OK]
Key=X-Frame-Options ,Value=[SAMEORIGIN]
Key=Alt-Svc ,Value=[quic=":443"; ma=2592000; v="44,43,39,35"]
Key=Vary ,Value=[X-Origin, Origin]
Key=Date ,Value=[Fri, 05 Oct 2018 12:26:57 GMT]
Key=Content-Length ,Value=[737]
Key=X-XSS-Protection ,Value=[1; mode=block]
Key=Expires ,Value=[Fri, 05 Oct 2018 12:26:57 GMT]
Key=Content-Type ,Value=[application/json; charset=UTF-8]
Key=Server ,Value=[GSE]
Key=X-Content-Type-Options ,Value=[nosniff]
Key=Cache-Control ,Value=[private, max-age=0, must-revalidate, no-transform]
Key=ResponseType ,Value=json
PROGRESS = 100%, DOWNLOADED=0 MB, TYPE=json
TIME REQUIRED=0 SECONDS!!!
{message=OK, outputFile=C:\Users\HP\AppData\Local\Temp\hello8652555977765600581.tmp, code=200, output=}

{files=[{id=1KRehy6fX-6WwWi4AAERUklXki8EqwoWh, name=Mine.txt, mimeType=text/plain, trashed=false, size=7, quotaBytesUsed=7}, {id=12EC7CqD4gY3w9SGefvpO_VQQubWGZ_Vb, name=CORE-ITEMS, mimeType=application/vnd.google-apps.folder, trashed=false, quotaBytesUsed=0}, {id=1rGwUE6XV2hfmv0NamUI-sfpdSSERdZ0j, name=[RePack] Full Version Game.zip, mimeType=application/x-zip-compressed, trashed=false, size=4832867859, quotaBytesUsed=4832867859}]}


{id=1KRehy6fX-6WwWi4AAERUklXki8EqwoWh, name=Mine.txt, mimeType=text/plain, trashed=false, size=7, quotaBytesUsed=7}


{id=12EC7CqD4gY3w9SGefvpO_VQQubWGZ_Vb, name=CORE-ITEMS, mimeType=application/vnd.google-apps.folder, trashed=false, quotaBytesUsed=0}

{id=1rGwUE6XV2hfmv0NamUI-sfpdSSERdZ0j, name=[RePack] Full Version Game.zip, mimeType=application/x-zip-compressed, trashed=false, size=4832867859, quotaBytesUsed=4832867859}

Java HttpURLConnection | HttpsURLConnection > Implement Pause / Resume in File Downloading > How to Extract Chunked Data When Using HttpURLConnection > Download File as Chunk

It's very important (as well as beneficial) if we can pause / resume our download specially when downloading big file.
Below is a code snippet to download data chunk by chunk. So you can now pause / resume your download whenever you want.
package com.pkm;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

public class JavaChunkDataDownload {
    public static enum Method {
        GET, POST, PUT, PATCH, DELETE
    }

    public static enum Type {
        XML, JSON, URL_ENCODED;
    };

    private static String fileName = "file2.zip";

    public static void main(String[] args) throws Exception {
        String URI = "http://ipv4.download.thinkbroadband.com/100MB.zip?t=" + System.currentTimeMillis();
        //URI = "http://localhost/ForDownload.zip?t=" + System.currentTimeMillis();
        Response response = execute(URI, Method.GET, "", Type.URL_ENCODED);
        println("Get_Result:\n" + lengthString(response.toString().replace("\n", ""), 400) + "...");
    }

    public static Response execute(String url, Method method, String data, Type type) {
        return execute(url, method, data, type, null, null);
    }

    private static Response execute(String requestURL, Method requestMethod, String requestData, Type dataType, Map headers, Integer timeOutMilli) {
        Long started = System.currentTimeMillis();
        String httpResponse = "", responseMessage = "";
        Integer httpCode = 0;
        timeOutMilli = timeOutMilli == null ? 1000 * 30 : timeOutMilli; /* Default read & write timeout */

        HttpURLConnection connection = null;
        try {
            String contentType = "", accept = "", contentLength = "" + requestData.length();
            switch (dataType) {
                case XML:
                    contentType = "text/xml; charset=utf-8";
                    accept = "text/xml";
                    break;
                case JSON:
                    contentType = "application/json";
                    break;
                case URL_ENCODED:
                    contentType = "application/x-www-form-urlencoded";
                    break;
            }

            connection = (HttpURLConnection) new URL(requestURL).openConnection();
            connection.setRequestMethod(requestMethod.name());
            connection.setConnectTimeout(timeOutMilli);
            connection.setReadTimeout(timeOutMilli);
            connection.setRequestProperty("Pragma", "no-cache");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");

            File outputFileCache = new File(fileName);
            if (outputFileCache.exists()) {
                connection.setAllowUserInteraction(true);
                connection.setRequestProperty("Range", "bytes=" + outputFileCache.length() + "-");
            }

            if (headers != null && headers.size() > 0) {
                for (Object name : headers.keySet().toArray()) {
                    connection.setRequestProperty(name.toString(), headers.get(name.toString()).toString());
                }
            }

            if (requestData.length() > 0) {
                connection.setDoInput(true);
                connection.setDoOutput(true);

                if (accept.length() > 0) {
                    connection.setRequestProperty("Accept", accept);
                }
                if (contentType.length() > 0) {
                    connection.setRequestProperty("Content-Type", contentType);
                }

                connection.setRequestProperty("Content_length", contentLength);
                OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
                writer.write(requestData);
                writer.flush();
                writer.close();
            }

            httpCode = connection.getResponseCode();
            Boolean validResponse = httpCode >= 200 && httpCode <= 299;
            responseMessage = connection.getResponseMessage();
            String responseContentType = connection.getContentType();
            if (responseContentType == null || responseContentType.length() == 0) {
                responseContentType = "txt";
            }
            else {
                if (responseContentType.contains(";")) {
                    responseContentType = responseContentType.substring(0, responseContentType.indexOf(";"));
                }
                if (responseContentType.contains("text/html")) {
                    responseContentType = "html";
                }
                else if (responseContentType.contains("image/")) {
                    responseContentType = "image";
                }
                else if (responseContentType.contains("/")) {
                    String[] parts = responseContentType.split("/");
                    responseContentType = parts[parts.length - 1];
                }
            }
            Map<String, List<String>> map = connection.getHeaderFields();
            for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                System.out.println("Key : " + entry.getKey() + " ,Value : " + entry.getValue());
            }

            if (validResponse) {
                Long downloadedSize = 0L;
                String connectionField = connection.getHeaderField("content-range");
                if (connectionField != null) {
                    String[] connectionRanges = connectionField.substring("bytes=".length()).split("-");
                    downloadedSize = Long.valueOf(connectionRanges[0]);
                }
                if (connectionField == null && outputFileCache.exists()) {
                    outputFileCache.delete();
                }
                outputFileCache = new File(fileName);
                if (!outputFileCache.exists()) {
                    outputFileCache.createNewFile();
                    outputFileCache.setExecutable(true);
                }
                Long fileLength = connection.getContentLength() + downloadedSize;
                RandomAccessFile output = new RandomAccessFile(outputFileCache, "rw");
                output.seek(downloadedSize);

                InputStream is = connection.getInputStream();
                BufferedInputStream input = new BufferedInputStream(is);

                int readSize = 1024;
                byte data[] = new byte[readSize];
                int count = 0;
                int progress = 0;
                Integer pauseAt = 180;

                Long timeNeeded = System.currentTimeMillis();
                while ((count = input.read(data, 0, readSize)) >= 0 && progress != 100)
                {
                    downloadedSize += count;
                    output.write(data, 0, count);
                    progress = (int) ((downloadedSize * 100) / fileLength);
                    Long mb = output.length() / (1024 * 1024);
                    System.out.println("PROGRESS = " + (progress) + "%, DOWNLOADED=" + mb + " MB, TYPE=" + responseContentType);
                    if (progress >= pauseAt) {
                        break;
                    }
                }
                output.close();
                input.close();

                timeNeeded = (System.currentTimeMillis() - timeNeeded) / 1000;
                System.out.println("TIME REQUIRED=" + timeNeeded);
            }
        }
        catch (Exception ex) {
            httpResponse = "";
            responseMessage = ex.getMessage();
        }
        finally {
            try {
                connection.disconnect();
            }
            catch (Exception ex10) {
            }
        }

        return new Response(requestURL, httpCode, responseMessage, httpResponse, (System.currentTimeMillis() - started));
    }

    public static class Response {
        private String url;
        private Integer code;
        private String message;
        private String body;
        private Long time;

        public Response(String url, Integer code, String message, String body, Long time) {
            this.url = url;
            this.code = code;
            this.message = message;
            this.body = body;
            this.time = time;
        }

        @Override
        public String toString() {
            return "{URL=" + this.url + ",Code=" + this.code + ", Message=" + this.message + ", Time=" + this.time + " Millis, Body=" + this.body + "}";
        }

        public Integer getCode() {
            return this.code;
        }

        public String getMessage() {
            return this.message;
        }

        public String getBody() {
            return this.body;
        }

        public Long getTime() {
            return this.time;
        }
    }

    public static void println(Object o) {
        System.out.println("" + o);
    }

    public static String lengthString(String s, Integer m) {
        return s.length() > m ? s.substring(0, m) : s;
    }
}