def test_build_error_invalid_input_directory_path(self): with pytest.raises(NotADirectoryError): Apktool().build("invalid.input.directory.path")
def test_build_error_invalid_input_directory(self, tmp_working_directory_path: str): invalid_directory_path = os.path.join(tmp_working_directory_path, "empty") os.makedirs(invalid_directory_path) with pytest.raises(subprocess.CalledProcessError): Apktool().build(invalid_directory_path)
def test_decode_error_invalid_output_directory( self, tmp_demo_apk_v10_original_path: str ): with pytest.raises(NotADirectoryError): Apktool().decode(tmp_demo_apk_v10_original_path, "invalid.directory")
def test_decode_error_invalid_apk_path(self): with pytest.raises(FileNotFoundError): Apktool().decode("invalid.apk.path")
def test_decode_valid_apk(self, tmp_demo_apk_v10_original_path: str): output = Apktool().decode(tmp_demo_apk_v10_original_path) assert "using apktool" in output.lower()
def test_apktool_wrong_path(self, monkeypatch): monkeypatch.setenv("APKTOOL_PATH", "invalid.apktool.path") with pytest.raises(RuntimeError): Apktool()
def decode_apk(self) -> None: if not self._is_decoded: # The input apk will be decoded with apktool. apktool: Apktool = Apktool() # <working_directory>/<apk_path>/ self._decoded_apk_path = os.path.join( self.working_dir_path, os.path.splitext(os.path.basename(self.apk_path))[0], ) try: apktool.decode(self.apk_path, self._decoded_apk_path, force=True) # Path to the decoded manifest file. self._manifest_file = os.path.join(self._decoded_apk_path, "AndroidManifest.xml") # A list containing the paths to all the smali files obtained with # apktool. self._smali_files = [ os.path.join(root, file_name) for root, dir_names, file_names in os.walk(self._decoded_apk_path) for file_name in file_names if file_name.endswith(".smali") ] if self.ignore_libs: # Normalize paths for the current OS ('.join(x, "")' is used to add # a trailing slash). libs_to_ignore = list( map( lambda x: os.path.join(os.path.normpath(x), ""), util.get_libs_to_ignore(), )) filtered_smali_files = [] for smali_file in self._smali_files: # Get the path without the initial part <root>/smali/. relative_smali_file = os.path.join(*( os.path.relpath(smali_file, self._decoded_apk_path ).split(os.path.sep)[1:])) # Get only the smali files that are not part of known third # party libraries. if not any( relative_smali_file.startswith(lib) for lib in libs_to_ignore): filtered_smali_files.append(smali_file) self._smali_files = filtered_smali_files # Sort the list of smali files to always have the list in the same # order. self._smali_files.sort() # Check if multidex. if os.path.isdir( os.path.join(self._decoded_apk_path, "smali_classes2")): self._is_multidex = True smali_directories = ["smali"] for i in range(2, 15): smali_directories.append("smali_classes{0}".format(i)) for smali_directory in smali_directories: current_directory = os.path.join( self._decoded_apk_path, smali_directory, "") if os.path.isdir(current_directory): self._multidex_smali_files.append([ smali_file for smali_file in self._smali_files if smali_file.startswith(current_directory) ]) # A list containing the paths to the native libraries included in the # application. self._native_lib_files = [ os.path.join(root, file_name) for root, dir_names, file_names in os.walk( os.path.join(self._decoded_apk_path, "lib")) for file_name in file_names if file_name.endswith(".so") ] # Sort the list of native libraries to always have the list in the # same order. self._native_lib_files.sort() except Exception as e: self.logger.error("Error during apk decoding: {0}".format(e)) raise else: self._is_decoded = True