Skip to content

Instantly share code, notes, and snippets.

@casidiablo
Created May 9, 2011 15:02
Show Gist options
  • Save casidiablo/962681 to your computer and use it in GitHub Desktop.
Save casidiablo/962681 to your computer and use it in GitHub Desktop.
'''
Feel free to modify and/or enhance this tool. Also feel free to fix bugs you found.
I would be happy if you could share your modified version on the blog, where this tool
was posted.
Blog-URL: http://www.droidnova.com/android-resource-tracker,723.html
Project Page: http://code.google.com/p/androidresourcetracker
This tool is from a developer for developers, so be like a good colleague and share your
improvements to this tool with the others.
EXPLIZIT: No license... I trust your good will... if you get rich, share with me :)
Created on 24.09.2010
@version: 1.0.1
@author: Martin Breuer (aka WarrenFaith)
'''
import sys
import os
import re
import glob
helpInformation = '''This is a tool that help you to find out, if a resource is used.
Parameter:
-h : shows this help
-i : root directory of your android project
-v : show all matches
--unused-only : shows only unused elements - does not work with --used-only
--used-only : shows on used elements - does not work with --unused-only
--types string:id:drawable : show only the specified types'''
rootProjectDir = None
elementPath = ""
verbose = False
usedOnly = False
unusedOnly = False
resourceArray = {}
sourceArray = {}
xmlFiles = []
resultArray = {}
inXml = 'inXml'
inSrc = 'inSrc'
unsure = 'unsure'
fetchOnly = []
## recursive walk through all directories ##
def findR(path):
for dirs in os.listdir(path):
if os.path.isdir(os.path.join(path, dirs)):
if dirs == '.svn':
break
return findR(os.path.join(path, dirs))
return path
def findXmlFiles(path):
for dirs in os.listdir(path):
if os.path.isdir(os.path.join(path, dirs)):
if dirs != '.svn':
findXmlFiles(os.path.join(path, dirs))
else:
if dirs.endswith(".xml"):
newPath = os.path.basename(path)
xmlFiles.append(os.path.join(newPath, dirs))
return None
def collectSources(path):
for dirs in os.listdir(path):
if os.path.isdir(os.path.join(path, dirs)):
if dirs == '.svn':
break
if not dirs.endswith('.java'):
sourceArray[os.path.join(path, dirs)] = []
collectSources(os.path.join(path, dirs))
return None
def parseR(pathToR):
patternResource = re.compile("\W(.+)\W(.+)=0x")
patternClass = re.compile("class\W(.+)\W{")
file = open(pathToR, "r")
currentClass = "ERROR";
for line in file:
resourceHit = patternResource.search(line)
classHit = patternClass.search(line)
if classHit != None and classHit.group(1) != "R":
currentClass = classHit.group(1)
resourceArray[currentClass] = []
if resourceHit != None:
resourceArray[currentClass] += [resourceHit.group(2)]
return None
def findPossibleMatchInSrc(type, item, searchString):
pattern = re.compile(searchString + item)
for dir in sourceArray:
for files in os.listdir(dir):
if files != ".svn" and files.endswith(".java"):
file = open(os.path.join(dir, files), "r")
lineNumber = 1
for line in file:
if pattern.search(line) != None:
if verbose:
print(files + " - Line: " + str(lineNumber) + " :: " + line.strip())
resultArray[type][item][unsure] = True
lineNumber += 1
return None
def findOccurenceInSrc(type, item, searchString):
pattern = re.compile(searchString + item)
for dir in sourceArray:
for files in os.listdir(dir):
if files != ".svn" and files.endswith(".java"):
file = open(os.path.join(dir, files), "r")
lineNumber = 1
for line in file:
if pattern.search(line) != None:
if verbose:
print(files + " - Line: " + str(lineNumber) + " :: " + line.strip())
resultArray[type][item][inSrc] = True
lineNumber += 1
return None
def findOccurenceInXml(type, item, plainTag, searchString):
if searchString == "@style/":
pattern = re.compile(searchString+"("+item+"|"+item.replace("_",".")+")")
else:
pattern = re.compile(searchString + item)
for files in xmlFiles:
file = open(os.path.join(elementPath, files), "r")
lineNumber = 1
for line in file:
if pattern.search(line) != None:
if verbose:
print(files + " - Line: " + str(lineNumber) + " :: " + line.strip())
resultArray[type][item][inXml] = True
lineNumber += 1
return None
### Main programm ###
if len(sys.argv) == 1:
print(helpInformation)
sys.exit()
for index,arg in enumerate(sys.argv):
if arg == "-h":
print(helpInformation)
sys.exit()
if arg == "-i":
if len(sys.argv) <= index + 1:
print('''Given path is missing...''')
sys.exit()
rootProjectDir = sys.argv[index + 1]
elementPath = os.path.join(rootProjectDir, "res")
if arg == "-v":
verbose = True
if arg == "--used-only":
usedOnly = True
if arg == "--unused-only":
unusedOnly = True;
if arg == "--types":
if len(sys.argv) <= index + 1:
print("Given element typ or types missing...")
sys.exit()
fetchOnly = sys.argv[index + 1].split(":")
if unusedOnly and usedOnly:
print('''--used-only and --unused-only can't be used together.
Remove one parameter...''')
sys.exit()
print("Processing, fetching, working...")
# collect all src files
collectSources(os.path.join(rootProjectDir, "src"))
# find all xml files
findXmlFiles(os.path.join(rootProjectDir, "res"))
#add manifest
xmlFiles.append(os.path.join(rootProjectDir, "AndroidManifest.xml"))
# read the R class
os.chdir(rootProjectDir)
for srcDirs in glob.glob('gen'):
rclass = os.path.join(findR(os.path.join(rootProjectDir, srcDirs)), "R.java")
parseR(rclass)
for entry in resourceArray:
resultArray[entry] = {}
for item in resourceArray[entry]:
resultArray[entry][item] = {}
resultArray[entry][item][inSrc] = False
resultArray[entry][item][inXml] = False
resultArray[entry][item][unsure] = False
findOccurenceInSrc(entry, item, entry + ".")
findOccurenceInXml(entry, item, entry + "." + item, "@" + entry + "/")
findPossibleMatchInSrc(entry, item, 'getIdentifier\(\s*?\"')
for type in resultArray:
if type in fetchOnly or len(fetchOnly) is 0:
for element,matches in resultArray[type].items():
if matches[inSrc] is False and matches[inXml] is False and matches[unsure] is False:
if usedOnly == False:
print("Unused: " + type + "." + element)
elif matches[inSrc] is True and matches[inXml] is True and matches[unsure] is True:
if unusedOnly == False:
print("Used in src and xml: " + type + "." + element)
elif matches[inSrc] is True or matches[unsure] is True and matches[inXml] is False:
if unusedOnly == False:
print("Used in src: " + type + "." + element)
elif matches[inSrc] is False and matches[unsure] is False and matches[inXml] is True:
if unusedOnly == False:
print("Used in xml: " + type + "." + element)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment