gt: 			f = new File(filePath);
context: package st.cs.uni.saarland.de.testApps;
  
  import com.thoughtworks.xstream.XStream;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import soot.PackManager;
  import soot.Transform;
  import st.cs.uni.saarland.de.dissolveSpecXMLTags.DissolveXMLTagsMain;
  import st.cs.uni.saarland.de.entities.*;
  import st.cs.uni.saarland.de.helpClasses.Helper;
  import st.cs.uni.saarland.de.saveData.SaveDataForTests;
  import st.cs.uni.saarland.de.searchDialogs.SearchDialogMain;
  import st.cs.uni.saarland.de.searchDynDecStrings.SearchDynDecMain;
  import st.cs.uni.saarland.de.searchListener.SearchListener;
  import st.cs.uni.saarland.de.searchMenus.SearchMenusMain;
  import st.cs.uni.saarland.de.searchScreens.SearchActivityScreens;
  import st.cs.uni.saarland.de.uiAnalysis.UiAnalysisPack;
  import st.cs.uni.saarland.de.xmlAnalysis.XMLParserMain;
  
  import java.io.*;
  import java.nio.charset.StandardCharsets;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Optional;
  import java.util.Set;
  import java.util.concurrent.TimeUnit;
  
  /* 
   * 
   * written by Isabelle Rommelfanger, November 2014 
   * 
   */
  
  public class Main_UI_Analysis {
  
  	private int errorCount;
  	private int appCount;
  	static final Logger logger =  LoggerFactory.getLogger(Thread.currentThread().getName());
  	private final TimeUnit tTimeoutUnit;
  	private final int tTimeoutValue;
  	private final int numThreads;
  	private final boolean isTest;
  	private final boolean processMenus;
  	private final int maxDepthMethodLevel;
  
  	// arg[0]: androidSDK path
  	// arg[1]: dir path of output Folder
  	// arg[2]: apk file path or dir of all apkFiles to anaylse
  
  //	public void recursiveSearchForAPKFiles(File out) {
  //
  //		// iter through all given apps in appDir if appsDir is a directory
  //		if (appsDir.isDirectory()) {
  //			File[] apkFiles = appsDir.listFiles();
  //			for (File apkFile : apkFiles) {
  //				this.recursiveSearchForAPKFiles(androidSDKPath, out, apkFile);
  //			}
  //		} else {
  //			if (appsDir.getName().endsWith(".apk")) {
  //				this.runAnalysisForOneApp(out);
  //			} else {
  //				logger.error("Potential APK File is not an apk file!:" + appsDir.getAbsolutePath());
  //			}
  //			;
  //
  //		}
  //	}
  
  	public Main_UI_Analysis(TimeUnit tTimeoutUnit, int tTimeoutValue, int numThreads, boolean processMenus, int maxDepthMethodLebel, boolean test){
  		this.tTimeoutUnit = tTimeoutUnit;
  		this.tTimeoutValue = tTimeoutValue;
  		this.numThreads = numThreads;
  		this.processMenus = processMenus;
  		this.isTest = test;
  		this.maxDepthMethodLevel = maxDepthMethodLebel;
  	}
  
  	// args:
  	public boolean runAnalysisForOneApp(File outputDir, boolean processImages) {
  
  
  		String logText = String.format("Running UI analysis with timeout for entrypoint class: %s %s", this.tTimeoutValue, this.tTimeoutUnit);
  		logger.info(logText);
  		Helper.saveToStatisticalFile(logText);
  
  		appCount++;
  
  		// save start time
  		long startTime = System.currentTimeMillis();
  		String appname = Helper.getApkName().replace(".apk", "");
  		String appOutputDir = outputDir.getAbsolutePath();
  
  		try {
  			// start analysis
  			logger.info("<Start Analysis for app nr: " + appCount + " : " + appname + ">");
  
  			// start apkTool
  			// extract xml structure of app with the help of the apkTool, for the given applicati
  
  			Content.getInstance(appOutputDir);
  			Application app = null;
  			try {
  				// XML analysis
  				// search for all UI elements and declared permissions in the XML files
  				XMLParserMain xmlparser = XMLParserMain.getInstance(appOutputDir);
  				app = xmlparser.xmlParserMain(processImages);
  			} catch (Exception e) {
  				e.printStackTrace();
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			}
  
  			// initialise appController
  			AppController.getInstance(app);
  
  
  			if(!isTest) {
  				final int countOfActivities = app.getActivities().size();
  				final long countOfXMlLayouts = app.getAllXMLLayoutFiles().stream().filter(x -> !(x instanceof Menu) && !x.getName().startsWith("abc_")).count();
  				if (countOfXMlLayouts / (double) (countOfActivities) < 0.7) {
  					String message = "App has less than 70% of XML Layouts.";
  					logger.error(message);
  					Helper.saveToStatisticalFile(message);
  					return false;
  				}
  			}
  
  			UiAnalysisPack uiAnalysisPack = new UiAnalysisPack(tTimeoutUnit, tTimeoutValue, numThreads, processMenus, maxDepthMethodLevel, app);
  			PackManager.v().getPack("wjtp").add(new Transform("wjtp.UiAnalysis", uiAnalysisPack));
  			PackManager.v().runPacks();
  			logger.info("UI Analysis Pack is done");
  
  			try {
  				logger.info("Resolving XML dependencies");
  //				 ressolve XMLTag dependencies
  				DissolveXMLTagsMain dissolveXMLTags = new DissolveXMLTagsMain();
  				dissolveXMLTags.dissolveXMLTags(uiAnalysisPack.getFragments(), uiAnalysisPack.getTabViews());
  			} catch (Exception e) {
  				logger.error(app.getName() + ": " + e.getMessage());
  				e.printStackTrace();
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			}
  
  			try {
  				// get the dynamical declared texts
  				logger.info("Searching for dynamically declared text");
  				SearchDynDecMain searchDynDec = new SearchDynDecMain();
  				searchDynDec.searchDynDeclaredStrings(uiAnalysisPack.getStrings());
  			} catch (Exception e) {
  				logger.error(app.getName() + ": " + e);
  				e.printStackTrace();
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			}
  
  
  			try {
  				// get all the UIElements, located at the one screen, together ~ grouping
  				logger.info("Grouping UI elements");
  				SearchActivityScreens screenMain = new SearchActivityScreens();
  				screenMain.runSearchActivityScreens(uiAnalysisPack.getLayouts());
  			} catch (Exception e) {
  				logger.error(app.getName() + ": " + e);
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			}
  
  			try {
  				logger.info("Processing menus");
  				SearchMenusMain searchMenus = new SearchMenusMain();
  				searchMenus.getMenusInApp(uiAnalysisPack.getOptionMenus(), uiAnalysisPack.getContextMenus(),
  						uiAnalysisPack.getContextOnCreateMenus(), uiAnalysisPack.getPopupMenus(), uiAnalysisPack.getNavigationMenus());
  			} catch (Exception e) {
  				logger.error(app.getName() + ": " + e);
  				e.printStackTrace();
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			}
  
  			try {
  				logger.info("Processing dialogs");
  				// search dynamical build Dialogs
  				SearchDialogMain diaMain = new SearchDialogMain();
  				diaMain.getDialogsOfApp(uiAnalysisPack.getDialogResults());
  			} catch (Exception e) {
  				logger.error(app.getName() + ": " + e.getMessage());
  				e.printStackTrace();
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			}
  
  			try {
  				logger.info("Processing listeners");
  				// search for listener
  				SearchListener sl = new SearchListener();
  				sl.runSearchListener(uiAnalysisPack.getListeners());
  			} catch (Exception e) {
  				logger.error(app.getName() + ": " + e);
  				e.printStackTrace();
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			}
  
  			//Mapping activities to layouts
  			final Set<Activity> activities = app.getActivities();
  			final Map<String, Set<Integer>> activityToXmlLayoutFiles = app.getActivityToXMLLayoutFiles();
  			activityToXmlLayoutFiles.keySet().forEach(acName -> {
  				Set<Integer> layoutIds = activityToXmlLayoutFiles.get(acName);
  				Optional<Activity> optionalActivity = activities.stream().filter(x -> x.getName().equals(acName)).findFirst();
  				if (optionalActivity.isPresent()) {
  					layoutIds.forEach(optionalActivity.get()::addXmlLayout);
  				}
  			});
  			for (Activity ac : app.getActivities()) {
  				if (ac.getLabel().startsWith("@string/")) {
  					ac.setLabel(Content.getInstance().getStringValueFromStringName(ac.getLabel().replace("@string/", "")));
  				}
  				else if(!ac.getLabel().isEmpty() && Character.isDigit(ac.getLabel().charAt(0))){
  					ac.setLabel(Content.getInstance().getStringValueFromStringId(ac.getLabel()));
  				}
  			}
  
  			// save the data of the UIElements with their listeners
  			try {
  				logger.info("Saving appSerialized");
  				this.getSerializedOutput(appOutputDir, app);
  //				this.saveElementsData(new File(appOutputDir + File.separator + "UIElements.txt"), app);
  //				this.saveOnlyButtonData(new File(appOutputDir + File.separator + "buttons.txt"), app);
  //				this.getScreensInFile(appOutputDir, app);
  				this.saveXMLLayoutFiles(appOutputDir, app);
  
  				this.saveClassToClassOrLayoutFile(appOutputDir, app);
  			} catch (IOException e1) {
  				e1.printStackTrace();
  				Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e1));
  			}
  
  			// save the results for testing purposes in a simple XML file
  			if (this.isTest) {
  				SaveDataForTests.getInstance().saveIDWithListenerAndText(app);
  				SaveDataForTests.getInstance().saveActivityToLayout(app);
  			}
  
  			// end of analysis for this app
  			logger.info("</Start Analysis>");
  			return true;
  		} catch (Exception e) {
  			logger.trace(appname + ": " + e);
  			e.printStackTrace();
  			Helper.saveToStatisticalFile(Helper.exceptionStacktraceToString(e));
  			throw e;
  		}
  	}
  
  	
  
  	private void saveActivityToLayout(String appOutputDir, Application app) throws IOException {
  		String list = "";
  
  		for (Entry<String, Set<Integer>> entry : app.getActivityToXMLLayoutFiles().entrySet()){
  			String res = "";
  			for (int id : entry.getValue())
  				res = res + id + "; ";
  			list = list + entry.getKey() + ": " +  res + "\n";
  		}
  
  
  		File f = createFile(appOutputDir, "activitiesToLayoutIds");
  
  		FileOutputStream writerStream = new FileOutputStream(f, true);
  		try {
  			byte[] b = list.getBytes();
  			writerStream.write(b);
  
  		} finally {
  			writerStream.close();
  		}
  
  	}
  	
  	private void saveClassToClassOrLayoutFile(String appOutputDir, Application app) throws IOException {
  		String list = "";
  
  		for (Entry<Integer, Set<Integer>> entry : app.getMergedLayoutFileIDs().entrySet()){
  			String res = "";
  			for (int id : entry.getValue())
  				res = res + id + "; ";
  			list = list + entry.getKey() + ": " +  res + "\n";
  		}
  
  
  		File f = createFile(appOutputDir, "classesToClasseOrLayoutMapping");
  
  		FileOutputStream writerStream = new FileOutputStream(f, true);
  		try {
  			byte[] b = list.getBytes();
  			writerStream.write(b);
  
  		} finally {
  			writerStream.close();
  		}
  
  	}
  
  	public File createFile(String path, String fileName) {
  		File f = null;
  		if ((path != null) && (!path.equals(""))) {
  			String filePath = path + File.separator + fileName + ".txt";
  
  