4141import java .io .IOException ;
4242import java .io .InputStream ;
4343import java .io .OutputStream ;
44+ import java .nio .file .DirectoryStream ;
45+ import java .nio .file .Files ;
46+ import java .nio .file .Path ;
47+ import java .nio .file .Paths ;
4448import java .text .DateFormat ;
4549import java .text .ParseException ;
4650import java .text .SimpleDateFormat ;
4751import java .util .ArrayList ;
4852import java .util .Date ;
53+ import java .nio .file .attribute .PosixFilePermission ;
4954
5055import java .io .PrintWriter ;
56+ import java .util .HashSet ;
57+ import java .util .Set ;
5158
5259/**
5360 * Class holding all needed references (path, tools, etc) to the SDK used by
@@ -69,6 +76,7 @@ class AndroidSDK {
6976 private final File cmdlineTools ;
7077 private final File avdManager ;
7178 private final File sdkManager ;
79+ private final File adb ;
7280
7381 private File emulator ;
7482
@@ -133,29 +141,50 @@ public AndroidSDK(File folder) throws BadSDKException, IOException {
133141
134142 // Retrieve the highest platform from the available targets
135143 ArrayList <SDKTarget > targets = getAvailableSdkTargets ();
136- int highest = 1 ;
144+ int highestIncremental = 1 ;
145+ int highestTarget = 1 ;
146+ String highestName = "" ;
137147 for (SDKTarget targ : targets ) {
138- if (highest < targ .version ) {
139- highest = targ .version ;
148+ if (highestIncremental < targ .version_incremental ) {
149+ highestIncremental = targ .version_incremental ;
150+ highestTarget = targ .version_sdk ;
151+ highestName = targ .name ;
140152 }
141153 }
142154
143- if (highest < PApplet .parseInt (AndroidBuild .TARGET_SDK )) {
155+ if (highestTarget < PApplet .parseInt (AndroidBuild .TARGET_SDK )) {
144156 throw new BadSDKException (AndroidMode .getTextString ("android_sdk.error.missing_target_platform" ,
145157 AndroidBuild .TARGET_SDK , platforms .getAbsolutePath ()));
146158 }
147-
148- highestPlatform = new File (platforms , "android-" + highest );
159+
160+ // Find the platform folder with the correct android.jar file.
161+ // Path platformPath = Paths.get(platforms.getAbsolutePath());
162+ // String highestPrefix = "android-" + highest;
163+ // File tmpFile;
164+ // try (DirectoryStream<Path> stream = Files.newDirectoryStream(platformPath, highestPrefix + "*")) {
165+ // for (Path entry: stream) {
166+ // if (Files.isDirectory(entry) && entry.getFileName().toString().startsWith(highestPrefix)) {
167+ // tmpFile = new File(entry.toString(), "android.jar");
168+ // if (tmpFile.exists()) {
169+ // System.out.println(tmpFile);
170+ // }
171+ // }
172+ // }
173+ // }
174+
175+ highestPlatform = new File (platforms , highestName );
149176
150177 androidJar = new File (highestPlatform , "android.jar" );
151178 if (!androidJar .exists ()) {
152179 throw new BadSDKException (AndroidMode .getTextString ("android_sdk.error.missing_android_jar" ,
153180 AndroidBuild .TARGET_SDK , highestPlatform .getAbsolutePath ()));
154181 }
155182
183+ // Collecting the tools needed by the mode
184+ adb = findCliTool (platformTools , "adb" );
156185 avdManager = findCliTool (new File (cmdlineTools , "bin" ), "avdmanager" );
157186 sdkManager = findCliTool (new File (cmdlineTools , "bin" ), "sdkmanager" );
158-
187+
159188 initEmu ();
160189
161190 String path = Platform .getenv ("PATH" );
@@ -392,18 +421,44 @@ static public File getGoogleDriverFolder() {
392421 * for the SDK installation. Also figures out the name of android/android.bat/android.exe
393422 * so that it can be called explicitly.
394423 */
395- private static File findCliTool (final File tools , String name )
424+ private static File findCliTool (final File toolDir , String toolName )
396425 throws BadSDKException {
397- if (new File (tools , name + ".bat" ).exists ()) {
398- return new File (tools , name + ".bat" );
426+ File toolFile = Platform .isWindows () ? new File (toolDir , toolName + ".exe" ) : new File (toolDir , toolName );
427+ if (!toolFile .exists ()) {
428+ throw new BadSDKException ("Cannot find " + toolName + " in " + toolDir );
399429 }
400- if (new File (tools , name + ".exe" ).exists ()) {
401- return new File (tools , name + ".exe" );
402- }
403- if (new File (tools , name ).exists ()) {
404- return new File (tools , name );
430+
431+ if (!Platform .isWindows ()) {
432+ try {
433+ // Get the POSIX file permissions
434+ Path toolPath = Paths .get (toolFile .getAbsolutePath ());
435+ Set <PosixFilePermission > permissions = Files .getPosixFilePermissions (toolPath );
436+
437+ // Print the file permissions
438+ System .out .println ("File permissions for " + toolPath + ":" );
439+ for (PosixFilePermission permission : permissions ) {
440+ System .out .println (permission );
441+ }
442+
443+ boolean addedPerm = false ;
444+ if (!permissions .contains (PosixFilePermission .OWNER_EXECUTE )) {
445+ permissions .add (PosixFilePermission .OWNER_EXECUTE );
446+ addedPerm = true ;
447+ }
448+ if (!permissions .contains (PosixFilePermission .GROUP_EXECUTE )) {
449+ permissions .add (PosixFilePermission .GROUP_EXECUTE );
450+ addedPerm = true ;
451+ }
452+
453+ if (addedPerm ) {
454+ Files .setPosixFilePermissions (toolPath , permissions );
455+ }
456+ } catch (Exception e ) {
457+ e .printStackTrace ();
458+ }
405459 }
406- throw new BadSDKException ("Cannot find " + name + " in " + tools );
460+
461+ return toolFile ;
407462 }
408463
409464
@@ -773,25 +828,20 @@ static public File selectFolder(String prompt, File folder, Frame frame) {
773828 private static final String ADB_DAEMON_MSG_1 = "daemon not running" ;
774829 private static final String ADB_DAEMON_MSG_2 = "daemon started successfully" ;
775830
776- public ProcessResult runADB (final String ... cmd )
831+ public ProcessResult runAdb (final String ... cmd )
777832 throws InterruptedException , IOException {
778833
779834 if (adbDisabled ) {
780835 throw new IOException ("adb is currently disabled" );
781836 }
782-
783- final String [] adbCmd ;
784- if (!cmd [0 ].contains ("adb" )) {
785- File abdPath = Platform .isWindows () ? new File (platformTools , "adb.exe" ) :
786- new File (platformTools , "adb" );
787- adbCmd = PApplet .splice (cmd , abdPath .getCanonicalPath (), 0 );
788- } else {
789- adbCmd = cmd ;
790- }
791- // printing this here to see if anyone else is killing the adb server
837+
838+ final String [] adbCmd = PApplet .splice (cmd , adb .getCanonicalPath (), 0 );
839+
792840 if (processing .app .Base .DEBUG ) {
841+ // printing this here to see if anyone else is killing the adb server
793842 PApplet .printArray (adbCmd );
794843 }
844+
795845 try {
796846 ProcessResult adbResult = new ProcessHelper (adbCmd ).execute ();
797847 // Ignore messages about starting up an adb daemon
@@ -821,12 +871,41 @@ public ProcessResult runADB(final String... cmd)
821871 }
822872 }
823873
824- static class SDKTarget {
825- public int version = 0 ;
826- public String name ;
874+ public Process getAdbProcess (final String ... cmd )
875+ throws IOException {
876+
877+ if (adbDisabled ) {
878+ throw new IOException ("adb is currently disabled" );
879+ }
880+
881+ final String [] adbCmd = PApplet .splice (cmd , adb .getCanonicalPath (), 0 );
882+
883+ if (processing .app .Base .DEBUG ) {
884+ // printing this here to see if anyone else is killing the adb server
885+ PApplet .printArray (adbCmd );
886+ }
887+
888+ try {
889+ Process process = Runtime .getRuntime ().exec (adbCmd );
890+ return process ;
891+ } catch (IOException ioe ) {
892+ if (-1 < ioe .getMessage ().indexOf ("Permission denied" )) {
893+ Messages .showWarning (AndroidMode .getTextString ("android_sdk.warn.cannot_run_adb_title" ),
894+ AndroidMode .getTextString ("android_sdk.warn.cannot_run_adb_body" ));
895+ adbDisabled = true ;
896+ }
897+ throw ioe ;
898+ }
899+ }
900+
901+ static private class SDKTarget {
902+ public int version_sdk = 0 ;
903+ public String version_release = "" ;
904+ public int version_incremental = 0 ;
905+ public String name = "" ;
827906 }
828907
829- public ArrayList <SDKTarget > getAvailableSdkTargets () throws IOException {
908+ private ArrayList <SDKTarget > getAvailableSdkTargets () throws IOException {
830909 ArrayList <SDKTarget > targets = new ArrayList <SDKTarget >();
831910
832911 for (File platform : platforms .listFiles ()) {
@@ -839,18 +918,24 @@ public ArrayList<SDKTarget> getAvailableSdkTargets() throws IOException {
839918 String line ;
840919 while ((line = br .readLine ()) != null ) {
841920 String [] lineData = line .split ("=" );
842- if (lineData [0 ].equals ("ro.build.version.sdk" )) {
843- target .version = Integer .valueOf (lineData [1 ]);
921+
922+ if (lineData [0 ].equals ("ro.system.build.version.incremental" )) {
923+ target .version_incremental = Integer .valueOf (lineData [1 ]);
844924 }
845925
846926 if (lineData [0 ].equals ("ro.build.version.release" )) {
847- target .name = lineData [1 ];
848- break ;
927+ target .version_release = lineData [1 ];
928+ }
929+
930+ if (lineData [0 ].equals ("ro.build.version.sdk" )) {
931+ target .version_sdk = Integer .valueOf (lineData [1 ]);
849932 }
933+
934+ target .name = platform .getName ();
850935 }
851936 br .close ();
852937
853- if (target .version != 0 && target .name != null ) targets .add (target );
938+ if (target .version_sdk != 0 && target .version_incremental != 0 && target . name != "" ) targets .add (target );
854939 }
855940
856941 return targets ;
0 commit comments