Java tutorial
package hu.tbognar76.apking; //Copyright 2016 tbognar76 // //Licensed under the Apache License, Version 2.0 (the "License"); //you may not use this file except in compliance with the License. //You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; import net.dongliu.apk.parser.ApkParser; import net.dongliu.apk.parser.bean.ApkMeta; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class ApKing { private Initialization init = null; public class CApkInfo { ComparableVersion cmp = null; ApkInfo apkinfo = null; boolean max = false; } // works with package name to determine the duplications HashMap<String, ArrayList<ApkInfo>> packageHash = null; // works with filename and size as cache HashMap<String, ApkInfo> serialInHash = null; HashMap<String, ApkInfo> serialOutHash = null; private DeviceManager dmanager = null; // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // START / MAIN // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void start() { this.init = new Initialization(); // Reads the property file this.init.initResources(); if (this.init.isCopyNewerFilesToUpdatePath) { // UPDATE PATH MUST BE EMPTY IF SET File ufile = new File(this.init.updatePath); if (ufile.isDirectory()) { if (ufile.list().length > 0) { System.out.println("Update Directory is not empty! : " + this.init.updatePath); System.exit(0); } } else { System.out.println("This is not a directory : this.updatePath"); System.exit(0); } } System.out.println("----------------------------------------------"); // STEP1 : REFRESH THE CACHES refreshCachefromAPK_READY(); // STEP 2: MANAGE IN_FOLDER System.out.println("----------------------------------------------"); System.out.println("IN FOLDER PROCESSING:"); File[] infiles = new File(this.init.inPath).listFiles(); moveFilesFromAPK_INtoAPK_READY(infiles, true, true); // STEP3 : REFRESH THE CACHES AGAIN System.out.println("----------------------------------------------"); refreshCachefromAPK_READY(); // STEP4 : REPORT and MOVE TO DELETE FOLDER System.out.println("----------------------------------------------"); System.out.println("REPORT AND DELETE:"); reportDuplications(true); // reportDuplications(false); // STEP 5 : update needed on phone System.out.println("----------------------------------------------"); System.out.println("PHONE TOOLS:"); dmanager = new DeviceManager(); dmanager.getInstalledPackagesFromPhone(); writePhoneCache(); // readPhoneCache(); System.out.println("Installed packages on Phone : " + this.dmanager.apps.size()); // reportPhoneRecognized(); System.out.println("SAME VERSION -----------------------------------"); reportPhoneSameVersion(); System.out.println("NEWER IN DB ------------------------------------"); reportPhoneNewerInDB(); System.out.println("NEWER ON PHONE----------------------------------"); reportPhoneNEWEROnPhone(); // STEP 6 : create catalog if (this.init.isCatalogGenerated) { createCatalog(); } System.out.println("----------------------------------------------"); System.out.println("READY!!!!!!!!!!!"); } private void reportPhoneNewerInDB() { ArrayList<String> log = new ArrayList<String>(); for (DeviceApp app : this.dmanager.apps) { // HashMap<String, ArrayList<ApkInfo>> packageHash = null; if (this.packageHash.get(app.packageName) != null) { // System.out.println(app.packageName); ArrayList<ApkInfo> aai = this.packageHash.get(app.packageName); for (ApkInfo ai : aai) { if (new ComparableVersion(ai.version).compareTo(new ComparableVersion(app.versionName)) > 0) { String line = concatWithPos(concatWithPos(ai.name, ai.version, 35), "on phone: " + app.versionName, 50); log.add(line); // ai.fullpath if (this.init.isCopyNewerFilesToUpdatePath) { Path sourcePath = Paths.get(ai.fullpath); Path destinationPath = Paths.get(this.init.updatePath + ai.filename); try { Files.copy(sourcePath, destinationPath); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } Collections.sort(log, (p1, p2) -> p1.compareTo(p2)); for (String line : log) { System.out.println(line); } } private void reportPhoneNEWEROnPhone() { ArrayList<String> log = new ArrayList<String>(); for (DeviceApp app : this.dmanager.apps) { // HashMap<String, ArrayList<ApkInfo>> packageHash = null; if (this.packageHash.get(app.packageName) != null) { // System.out.println(app.packageName); ArrayList<ApkInfo> aai = this.packageHash.get(app.packageName); for (ApkInfo ai : aai) { if (new ComparableVersion(ai.version).compareTo(new ComparableVersion(app.versionName)) < 0) { String line = concatWithPos(concatWithPos(ai.name, ai.version, 35), "on phone: " + app.versionName, 50); log.add(line); } } } } Collections.sort(log, (p1, p2) -> p1.compareTo(p2)); for (String line : log) { System.out.println(line); } } private void reportPhoneSameVersion() { ArrayList<String> log = new ArrayList<String>(); for (DeviceApp app : this.dmanager.apps) { // HashMap<String, ArrayList<ApkInfo>> packageHash = null; if (this.packageHash.get(app.packageName) != null) { // System.out.println(app.packageName); ArrayList<ApkInfo> aai = this.packageHash.get(app.packageName); for (ApkInfo ai : aai) { if (new ComparableVersion(ai.version).compareTo(new ComparableVersion(app.versionName)) == 0) { String line = concatWithPos(concatWithPos(ai.name, ai.version, 35), "on phone: " + app.versionName, 50); log.add(line); } } } } Collections.sort(log, (p1, p2) -> p1.compareTo(p2)); // for (String line : log) { // System.out.println(line); // } System.out.println("Number of: " + log.size()); } private void reportPhoneRecognized() { for (DeviceApp app : this.dmanager.apps) { // HashMap<String, ArrayList<ApkInfo>> packageHash = null; if (this.packageHash.get(app.packageName) != null) { ArrayList<ApkInfo> aai = this.packageHash.get(app.packageName); for (ApkInfo ai : aai) { System.out.println(concatWithPos(concatWithPos(ai.name, ai.version, 35), "on phone: " + app.versionName, 50)); } } } } private void refreshCachefromAPK_READY() { File[] files = new File(this.init.outPath).listFiles(); // REREAD THE CACHES // Init VARIABLES this.packageHash = new HashMap<String, ArrayList<ApkInfo>>(); this.serialInHash = new HashMap<String, ApkInfo>(); this.serialOutHash = new HashMap<String, ApkInfo>(); // Loads the cache, fills the "serialInHash" readInCache(); // Update structures from APK_READY // Using INCACHE // Filling OUTCACHE // Filling packageHash group by package updateHashFromAPK_READY(files); // Writes down the changes writeOutCache(); System.out.println( "Cache refreshed! (IN:" + this.serialInHash.size() + " OUT:" + this.serialOutHash.size() + ")"); } // REPORTS from "packageHash" // DELETES OLD VERSIONS IF PARAMETER "TRUE" private void reportDuplications(boolean toDelete) { for (Map.Entry<String, ArrayList<ApkInfo>> entry : this.packageHash.entrySet()) { // String key = entry.getKey(); ArrayList<ApkInfo> value = entry.getValue(); if (value.size() > 1) { ArrayList<CApkInfo> cvalue = new ArrayList<ApKing.CApkInfo>(); System.out.println(""); List<Version> versions = new ArrayList<Version>(); boolean versionerror = false; boolean versionerror2 = false; for (ApkInfo ai : value) { CApkInfo cai = new CApkInfo(); cai.apkinfo = ai; // System.out.println(ai.fullpath + " " + ai.version); try { versions.add(new Version(ai.version)); } catch (Exception e) { versionerror = true; } try { cai.cmp = new ComparableVersion(ai.version); } catch (Exception e) { versionerror2 = true; } cvalue.add(cai); } if (versionerror2) { System.out.println("BAD VERSION FORMAT 2"); for (ApkInfo ais : value) { System.out.println("#del " + ais.fullpath); } } else { CApkInfo maxi = Collections.max(cvalue, new Comparator<CApkInfo>() { @Override public int compare(CApkInfo left, CApkInfo right) { return left.cmp.compareTo(right.cmp); } }); maxi.max = true; String warning = ""; if (versionerror || versionerror2) { warning = "WARNING!! "; } String vers = ""; for (CApkInfo aic : cvalue) { if (aic.max) { vers = vers + "-->" + aic.apkinfo.version + "<-- , "; } else { vers = vers + aic.apkinfo.version + " , "; } } System.out.println("::" + warning + maxi.apkinfo.name + " // " + vers); for (CApkInfo aic : cvalue) { // String max ; if (aic.max) { // max = "rem #"; // A LEGUJABB System.out.println("!OK " + aic.apkinfo.fullpath); } else { // REGEBBI , TOROLNI KELL (MOVE TO DELETEFOLDER) System.out.println("del " + aic.apkinfo.fullpath); if (toDelete) { String renamedfile = this.init.deletePath + "/" + FilenameUtils.getName(aic.apkinfo.fullpath); File file = new File(aic.apkinfo.fullpath); if (file.renameTo(new File(renamedfile))) { } else { System.out.println("File is failed to move!" + renamedfile); } } } } } // System.out.println("MAX: " + maxi.apkinfo.version + // " "+maxi.apkinfo.filename); } // do stuff } } // USES packageHash private void moveFilesFromAPK_INtoAPK_READY(File[] files, boolean isSamePackageFeature, boolean isGooglePlayCategoryFeauture) { for (File file : files) { if (file.isDirectory()) { // System.out.println("Directory: " + file.getName()); moveFilesFromAPK_INtoAPK_READY(file.listFiles(), isSamePackageFeature, isGooglePlayCategoryFeauture); // Calls // same // method again. } else { // System.out.println("File: " + file.getName()); // System.out.println("File: " + file.getPath()); // it will put the new APK in a same folder where the old one // was (in a same folder) (by package name) ApkInfo apkinfo = null; ApkMeta apkMeta = null; apkMeta = getPackage(file.getPath()); if (isSamePackageFeature) { if (packageHash.containsKey(apkMeta.getPackageName())) { // FOUND ArrayList<ApkInfo> apkinfos = packageHash.get(apkMeta.getPackageName()); // If more then the select the first apkinfo = apkinfos.get(0); // } // apkinfo.fullpath String pathOLD = FilenameUtils.getFullPath(apkinfo.fullpath); String filenameOLD = FilenameUtils.getName(apkinfo.fullpath); String filenameNEW = FilenameUtils.getName(file.getPath()); if (filenameOLD.equals(filenameNEW)) { filenameNEW = FilenameUtils.getBaseName(file.getPath()) + "_(new)." + FilenameUtils.getExtension(file.getPath()); } if (this.init.isMoveFromIN) { if (file.renameTo(new File(pathOLD + filenameNEW))) { } else { System.out.println("File is failed to move next to its prev version! " + pathOLD + filenameNEW); } } System.out.println("Moved " + concatWithPos(filenameNEW, " to " + pathOLD, 30)); } } if (isGooglePlayCategoryFeauture && apkinfo == null) { GoogleCategory cc = new GoogleCategory(); if (apkMeta != null) { String packname = apkMeta.getPackageName(); // System.out.println(file.getName()+" "+packname); if (packname == null || packname.equals("")) { System.out.println("ERROR PASING PACKAGE: " + file.getName()); cc.cat1 = "Unknown"; cc.cat2 = "Unknown Package"; } else { // // Google Play parser call! // cc = getCategoryFromGooglePlayStore(packname); } } else { System.out.println("ERROR PARSING PACKAGE 2: " + file.getName()); cc.cat1 = "Unknown"; cc.cat2 = "Unknown Package"; } String renamedfile = this.init.outPath + "/" + cc.cat1 + "/" + cc.cat2 + "/" + file.getName(); String renamedpath1 = this.init.outPath + "/" + cc.cat1 + "/"; String renamedpath2 = this.init.outPath + "/" + cc.cat1 + "/" + cc.cat2 + "/"; // create dirs move files if (this.init.isMoveFromIN) { makeDir(renamedpath1); makeDir(renamedpath2); if (file.renameTo(new File(renamedfile))) { } else { System.out.println("File is failed to move!" + renamedfile); } } System.out.println(concatWithPos(concatWithPos(cc.cat1, cc.cat2, 12), file.getName(), 40)); } } } } // List all files in APK_READY // Using INCACHE // Filling OUTCACHE // Filling packageHash group by package private void updateHashFromAPK_READY(File[] files) { for (File file : files) { if (file.isDirectory()) { // System.out.println("Directory: " + file.getName()); updateHashFromAPK_READY(file.listFiles()); // Calls same method // again. } else { // System.out.println("File: " + file.getName()); // System.out.println("File: " + file.getPath()); ApkInfo ai = null; if (!isInCache(file)) { ai = getApkInfo(file); addToOutCache(ai); } else { ai = getFromCache(file); } if (packageHash.containsKey(ai.packname)) { // if we have packageHash.get(ai.packname).add(ai); } else { ArrayList<ApkInfo> l = new ArrayList<ApkInfo>(); l.add(ai); packageHash.put(ai.packname, l); } /* * if (apkMeta != null) { String packname = * apkMeta.getPackageName(); // * System.out.println(file.getName()+" "+packname); if * (packname == null || packname.equals("")) { * System.out.println("ERROR PASING PACKAGE: " + * file.getName()); } else { hm.get(packname) } } else { * System.out.println("ERROR PARSING PACKAGE 2: " + * file.getName()); * * } * * String renamedfile = outPath + "/" + cc.cat1 + "/" + cc.cat2 * + "/" + file.getName(); String renamedpath1 = outPath + "/" + * cc.cat1 + "/"; String renamedpath2 = outPath + "/" + cc.cat1 * + "/" + cc.cat2 + "/"; */ // System.out.println(addStr( // addStr(cc.cat1,cc.cat2,12),file.getName(),40)); } } } private void makeDir(String path) { File dir = new File(path); if (!dir.exists()) { if (dir.mkdir()) { // System.out.println("Directory is created!"); } else { System.out.println("Failed to create directory!"); } } } public GoogleCategory getCategoryFromGooglePlayStore(String packageName) { GoogleCategory cc = new GoogleCategory(); cc.cat1 = "Unknown"; cc.cat2 = "Unknown"; String url = "https://play.google.com/store/apps/details?id=" + URI.create(packageName) + "&hl=en"; Document doc = null; try { doc = Jsoup.connect(url).get(); } catch (IOException e) { // TODO Auto-generated catch block // e.printStackTrace(); System.out.println("!! GooglePlay connect error with : " + url); return cc; } // <span itemprop="genre">letstlus</span> /* * Elements link = doc.select(".document-subtitle category"); String * linkHref = link.attr("href"); // "http://example.com/" String * linkText = link.text(); // "example"" */ Elements genres = doc.select("a[itemprop=genre]"); if (genres != null) { Element e = genres.first(); if (e != null) { cc.cat2 = e.text(); String hr = e.attr("href"); if (hr.indexOf("category/GAME") != -1 || hr.indexOf("category/FAMILY") != -1) { cc.cat1 = "Game"; } else { cc.cat1 = "Application"; } } else { System.out.println("!! GooglePlay parse error structure with : " + url); } } else { System.out.println("!! GooglePlay parse error with : " + url); } /* * for (Element e : genres) { // System.out.println(e.text()); if * (!out.equals("")) { out = out + " "; } out = out + e.text(); * * } */ // <div class="content" itemprop="softwareVersion"> 2.6.9.0 </div> // Elements versions = doc.select("div[itemprop=softwareVersion]"); // System.out.println(versions.first().text()); // <a class="document-subtitle category" // href="/store/apps/category/GAME_ADVENTURE"> <span // itemprop="genre">Kalandjtkok</span> </a> /* Elements maincat = doc.getElementsByClass("category"); if (maincat != null) { Element p = maincat.first(); if (p != null) { String href = maincat.attr("href"); if (href != null) { if ((href.lastIndexOf("GAME") != -1) || (href.lastIndexOf("FAMILY") != -1)) { cc.cat1 = "Game"; } else { cc.cat1 = "Application"; } } // cc.cat1 = maincat.attr("href"); } } */ // <img alt="PEGI 3" class="document-subtitle content-rating-badge" // src="//lpfw=h28"> // <span class="document-subtitle content-rating-title">PEGI 3</span> Elements pegi = doc.getElementsByClass("content-rating-title"); if (pegi != null) { Element p = pegi.first(); if (p != null) { // cc.cat1 = p.text(); } } return cc; } private ApkMeta getPackage(String filePath) { ApkParser apkParser = null; try { apkParser = new ApkParser(new File(filePath)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // set a locale to translate resource tag into specific strings in // language the locale specified, you set locale to Locale.ENGLISH then // get apk title 'WeChat' instead of '@string/app_name' for example Locale locale = Locale.ENGLISH; apkParser.setPreferredLocale(locale); /* * String xml = null; try { xml = apkParser.getManifestXml(); } catch * (IOException e) { // TODO Auto-generated catch block * e.printStackTrace(); } System.out.println(xml); */ // String xml2 = apkParser.transBinaryXml(xmlPathInApk); // System.out.println(xml2); ApkMeta apkMeta = null; try { apkMeta = apkParser.getApkMeta(); } catch (Exception e) { // TODO Auto-generated catch block // e.printStackTrace(); return null; } // System.out.println(apkMeta); /* * Set<Locale> locales = null; try { locales = apkParser.getLocales(); } * catch (IOException e) { // TODO Auto-generated catch block * e.printStackTrace(); } for (Locale l : locales) { * System.out.println(l); } */ try { apkParser.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return apkMeta; } private ApkInfo getApkInfo(File file) { String filePath = file.getPath(); ApkInfo ai = new ApkInfo(); ApkParser apkParser = null; try { apkParser = new ApkParser(new File(filePath)); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("Error: " + filePath); e.printStackTrace(); } // set a locale to translate resource tag into specific strings in // language the locale specified, you set locale to Locale.ENGLISH then // get apk title 'WeChat' instead of '@string/app_name' for example Locale locale = Locale.ENGLISH; apkParser.setPreferredLocale(locale); /* * String xml = null; try { xml = apkParser.getManifestXml(); } catch * (IOException e) { // TODO Auto-generated catch block * e.printStackTrace(); } System.out.println(xml); */ // String xml2 = apkParser.transBinaryXml(xmlPathInApk); // System.out.println(xml2); ApkMeta apkMeta = null; try { apkMeta = apkParser.getApkMeta(); } catch (Exception e) { // TODO Auto-generated catch block // e.printStackTrace(); return null; } ai.packname = apkMeta.getPackageName(); ai.version = apkMeta.getVersionName(); ai.versioncode = apkMeta.getVersionCode(); ai.name = apkMeta.getName(); ai.filename = file.getName(); ai.fullpath = file.getPath(); ai.filesize = file.length(); // System.out.println(apkMeta); // Files.getAttribute( file.getPath(), "basic:createdAt", arg2) /* * Set<Locale> locales = null; try { locales = apkParser.getLocales(); } * catch (IOException e) { // TODO Auto-generated catch block * e.printStackTrace(); } for (Locale l : locales) { * System.out.println(l); } */ try { apkParser.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ai; } private String concatWithPos(String s1, String s2, int pos) { if ((s1 == null) || (s2 == null) || ("".equals(s1)) || ("".equals(s2))) return s1 + s2; String out = s1; for (; out.length() < pos; out = out + " ") { } out = out.substring(0, pos); return out + s2; } ApkInfo ai = null; private boolean isInCache(File file) { String key = file.getName() + file.length(); return this.serialInHash.containsKey(key); } private void addToOutCache(ApkInfo ai) { String key = ai.filename + ai.filesize; if (!this.serialOutHash.containsKey(key)) { this.serialOutHash.put(key, ai); } } private ApkInfo getFromCache(File file) { String key = file.getName() + file.length(); ApkInfo val = this.serialInHash.get(key); // if the directory has changed val.fullpath = file.getPath(); this.serialOutHash.put(key, val); return val; } private void writeOutCache() { try { FileOutputStream fileOut = new FileOutputStream(this.init.serialCache); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(this.serialOutHash); /* * for (Map.Entry<String, ApkInfo> entry : * this.serialHash.entrySet()) { out.writeObject(entry.getValue()); * } */ out.close(); fileOut.close(); // System.out.println("Cache writen: " + this.serialCache + // " cache size: " + this.serialOutHash.size()); } catch (IOException i) { i.printStackTrace(); } } @SuppressWarnings("unchecked") private void readInCache() { try { FileInputStream fileIn = new FileInputStream(this.init.serialCache); ObjectInputStream in = new ObjectInputStream(fileIn); this.serialInHash = (HashMap<String, ApkInfo>) in.readObject(); in.close(); fileIn.close(); // System.out.println("Cache loaded: " + this.serialCache + // " cache size: " + this.serialInHash.size()); } catch (IOException i) { System.out.println("No Cache!!"); return; } catch (ClassNotFoundException c) { c.printStackTrace(); return; } } private void writePhoneCache() { try { FileOutputStream fileOut = new FileOutputStream(this.init.phoneCache); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(this.dmanager.apps); out.close(); fileOut.close(); // System.out.println("Cache writen: " + this.serialCache + // " cache size: " + this.serialOutHash.size()); } catch (IOException i) { i.printStackTrace(); } } private void readPhoneCache() { try { FileInputStream fileIn = new FileInputStream(this.init.phoneCache); ObjectInputStream in = new ObjectInputStream(fileIn); @SuppressWarnings("unchecked") ArrayList<DeviceApp> readObject = (ArrayList<DeviceApp>) in.readObject(); this.dmanager.apps = readObject; in.close(); fileIn.close(); // System.out.println("Cache loaded: " + this.serialCache + // " cache size: " + this.serialInHash.size()); } catch (IOException i) { System.out.println("No Cache!!"); return; } catch (ClassNotFoundException c) { c.printStackTrace(); return; } } private void createCatalog() { System.out.println("----------------------------------------------"); System.out.println("Generating catalog to : " + this.init.catalogHtml); File catfile = new File(this.init.catalogHtml + "/index.html"); HashMap<String, String> types = new HashMap<String, String>(); try { FileUtils.copyFile(new File("html/noicon.png"), new File(this.init.catalogHtml + "/" + this.init.catalogPic + "noicon.png")); FileWriter fileWriter = new FileWriter(catfile); // fileWriter.write("<html><head></head><body>"); String fhead = FileUtils.readFileToString(new File("html/catalog_head.html")); String ftail = FileUtils.readFileToString(new File("html/catalog_tail.html")); StringBuffer ftags = new StringBuffer(); StringBuffer felements = new StringBuffer(); for (Map.Entry<String, ApkInfo> entry : this.serialOutHash.entrySet()) { // String key = entry.getKey(); ApkInfo ai = entry.getValue(); // System.out.println(value.toString()); String fullpath = ai.fullpath; fullpath = fullpath.replace("\\", "/"); fullpath = fullpath.replace(this.init.outPath, ""); fullpath = fullpath.replace(ai.filename, ""); fullpath = fullpath.replace(" ", "-"); fullpath = fullpath.trim(); for (String s : fullpath.split("/")) { if (!s.equals("")) { types.put(s, s); } } fullpath = fullpath.replace("/", " "); fullpath = fullpath.trim(); StringBuffer sb = new StringBuffer(); sb.append("<div class=\"elem " + fullpath + "\">\n"); String iname = ai.packname; if (!isLocalVersionGooglePlayImage(ai.packname)) { iname = "noicon"; } sb.append("<img class=\"coverimg\" src=\"" + this.init.catalogPic + "/" + iname + ".png\"></img>"); sb.append("<div class=\"name\">"); sb.append("<a href=\"https://play.google.com/store/apps/details?id=" + URI.create(ai.packname) + "&hl=en\" target=\"_blank\" >" + ai.name + "</a>"); sb.append(" ( <span class=\"version\">" + ai.version + "</span>)"); sb.append("</div>\n"); sb.append("</div>\n"); felements.append(sb); } ftags.append("<div id=\"selector\">"); Map<String, String> sortedTypes = types.entrySet().stream().sorted(Map.Entry.comparingByKey()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); for (Map.Entry<String, String> entry : sortedTypes.entrySet()) { ftags.append("<a id=\"" + entry.getKey() + "-button\" href=\"#\" class=\"button\" >" + entry.getKey() + "</a>"); } ftags.append("</div>"); fileWriter.write(fhead); fileWriter.write(ftags.toString()); fileWriter.write(felements.toString()); fileWriter.write(ftail); fileWriter.flush(); fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("Done!"); } private boolean isLocalVersionGooglePlayImage(String packageName) { String fname = this.init.catalogHtml + "/" + this.init.catalogPic + "/" + packageName + ".png"; if (!this.init.isCatalogPicForced) { File t = new File(fname); if (t.exists()) { // System.out.println("------"+fname); if (t.length() > 1) { return true; } return false; } else { // WORK TO DO BELOW } } Document doc = null; try { doc = Jsoup .connect("https://play.google.com/store/apps/details?id=" + URI.create(packageName) + "&hl=en") .get(); // Joni j, de nha nem // Elements img = doc.getElementsByClass("cover-image"); Elements img = doc.select("div.cover-container img"); String uu = "http:" + img.first().attr("src"); uu = uu.replace("http:https:", "https:"); uu = uu.replace("=w300", "=w120"); URL url = new URL(uu); FileUtils.copyURLToFile(url, new File(fname)); } catch (Exception e) { try { FileUtils.write(new File(fname), "-"); return false; } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } return true; } }