修改Android Studio项目配置JDK路径和项目Gradle路径的GUI工具

概述

本工具提供了一个基于Python Tkinter的图形用户界面(GUI),用于帮助用户搜索并更新Android Studio项目中的config.properties文件里的java.home路径,以及workspace.xml文件中的last_opened_file_path路径。该工具旨在简化手动查找和编辑这些配置文件的过程,提高工作效率。

系统要求

  • Python 3.x
  • Tkinter库(通常随Python一起安装)

安装步骤

  1. 确保你的系统上已经安装了Python 3.x。

  2. 将上述提供的Python脚本保存到一个文件中,例如命名为config_editor.py

  3. 打开命令行工具(如CMD、PowerShell或终端)。

  4. 导航到包含config_editor.py文件的目录。

  5. 运行脚本:

    复制代码
    python 复制代码
    import tkinter as tk
    from tkinter import scrolledtext
    import os
    import xml.etree.ElementTree as ET
    import json
    
    # 定义查找配置配置文件的函数
    def find_properties_files(directory):
        found_files = []
        for root, dirs, files in os.walk(directory):
            for file in files:
                if file.lower() == 'config.properties':
                    found_files.append(os.path.join(root, file))
        return found_files
    
    # 定义读取java.home的函数
    def read_java_home(file_path):
        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                for line in file:
                    if line.lower().startswith('java.home='):
                        return line.strip()
        except Exception as e:
            log_text.insert(tk.END, f"读取配置文件 {file_path} 失败: {e}\n")
        return None
    
    # 定义写入java.home的函数
    def write_java_home(file_path, new_line):
        try:
            with open(file_path, 'r+', encoding='utf-8') as file:
                lines = file.readlines()
                file.seek(0)
                file.truncate()
                found = False
                for line in lines:
                    if line.lower().startswith('java.home='):
                        file.write(new_line + '\n')
                        found = True
                    else:
                        file.write(line)
                if not found:
                    file.write(new_line + '\n')
        except Exception as e:
            log_text.insert(tk.END, f"写入配置文件 {file_path} 失败: {e}\n")
    
    # 搜索按钮点击事件
    def on_search():
        directory = search_entry.get().strip()
        if not directory:
            directory = os.getcwd()
    
        log_text.delete(1.0, tk.END)
    
        found_files = find_properties_files(directory)
        if not found_files:
            status_label.config(text="没有找到任何config.properties配置文件")
            log_text.insert(tk.END, "没有找到任何config.properties配置文件\n")
        else:
            status_label.config(text=f"找到 {len(found_files)} 个config.properties配置文件")
            log_text.insert(tk.END, f"找到 {len(found_files)} 个config.properties配置文件\n")
            for file_path in found_files:
                log_text.insert(tk.END, f"处理配置文件: {file_path}\n")
    
    # 更新按钮点击事件
    def on_update():
        new_value = entry_new_value.get().strip()
        if not new_value:
            #log_text.insert(tk.END, "新的java.home路径不能为空\n")
            status_label.config(text=f"新的java.home路径不能为空")
            return
    
        log_text.delete(1.0, tk.END)
    
        directory = search_entry.get().strip()
        if not directory:
            directory = os.getcwd()
    
        log_text.insert(tk.END, f"目标路径: {directory}\n")
    
        found_files = find_properties_files(directory)
        if not found_files:
            status_label.config(text="没有找到任何config.properties配置文件")
            log_text.insert(tk.END, "没有找到任何config.properties配置文件\n")
        else:
            status_label.config(text=f"找到 {len(found_files)} 个config.properties配置文件")
            log_text.insert(tk.END, f"找到 {len(found_files)} 个config.properties配置文件\n")
            for file_path in found_files:
                log_text.insert(tk.END, f"处理配置文件: {file_path}\n")
                current_java_home = read_java_home(file_path)
                if current_java_home:
                    log_text.insert(tk.END, f"配置文件路径: {file_path}, 当前值: {current_java_home}, 已更新: java.home={new_value}\n")
                else:
                    log_text.insert(tk.END, f"配置文件路径: {file_path}, 未找到java.home属性, 已更新: java.home={new_value}\n")
                write_java_home(file_path, f"java.home={new_value}")
    
    # 搜索workspace.xml配置文件
    def on_workspace_xml_search():
        directory = search_entry.get().strip()
        if not directory:
            directory = os.getcwd()
    
        log_text.delete(1.0, tk.END)
    
        found_files = []
        for root, dirs, files in os.walk(directory):
            for file in files:
                if file.lower() == 'workspace.xml':
                    found_files.append(os.path.join(root, file))
    
        if not found_files:
            log_text.insert(tk.END, "没有找到workspace.xml配置文件\n")
        else:
            status_label.config(text=f"找到 {len(found_files)} 个workspace.xml配置文件")
            log_text.insert(tk.END, f"找到 {len(found_files)} 个workspace.xml配置文件\n")
            for file_path in found_files:
                log_text.insert(tk.END, f"处理配置文件: {file_path}\n")
    
    # 更新workspace.xml配置文件
    def on_workspace_xml_update():
        directory = search_entry.get().strip()
        if not directory:
            directory = os.getcwd()
    
        log_text.delete(1.0, tk.END)
    
    import json
    import os
    import tkinter as tk
    from lxml import etree
    
    # 更新workspace.xml配置文件
    def on_workspace_xml_update():
        directory = search_entry.get().strip()
        if not directory:
            directory = os.getcwd()
    
        # 获取新的 last_opened_file_path
        new_last_opened_file_path = new_last_opened_file_path_entry.get().strip()
        if not new_last_opened_file_path:
            messagebox.showerror("错误", "新的last_opened_file_path不能为空")
            
            return
    
        # 确保路径使用正斜杠
        new_last_opened_file_path = new_last_opened_file_path.replace("\\", "/")
    
        # 查找workspace.xml配置文件
        found_files = []
        for root, dirs, files in os.walk(directory):
            for file in files:
                if file.lower() == 'workspace.xml':
                    found_files.append(os.path.join(root, file))
    
        if not found_files:
            messagebox.showinfo("信息", "没有找到workspace.xml配置文件")
            return
    
        for workspace_xml_path in found_files:
            log_text.insert(tk.END, f"处理配置文件: {workspace_xml_path}\n")
    
            try:
                # 读取并解析XML配置文件
                parser = etree.XMLParser(strip_cdata=False)  # 保持CDATA部分不变
                tree = etree.parse(workspace_xml_path, parser)
                root = tree.getroot()
    
                # 查找PropertiesComponent组件
                properties_component = root.find(".//component[@name='PropertiesComponent']")
                if properties_component is None:
                    log_text.insert(tk.END, "找不到 PropertiesComponent 组件\n")
                    continue
    
                # 提取CDATA内容
                cdata_content = properties_component.text
                if not cdata_content or not cdata_content.strip().startswith("<![CDATA[") or not cdata_content.strip().endswith("]]>"):
                    log_text.insert(tk.END, "找不到 PropertiesComponent 组件或其 JSON 数据\n")
                    continue
    
                # 去掉CDATA标记
                key_to_string_json = cdata_content.strip()[len("<![CDATA["):-len("]]>")].strip()
                log_text.insert(tk.END, f"原始 keyToString JSON 数据: {key_to_string_json}\n")
    
                # 使用json.loads解析JSON数据
                key_to_string_dict = json.loads(key_to_string_json, strict=False)
    
                # 获取旧的 last_opened_file_path
                old_last_opened_file_path = key_to_string_dict.get('keyToString', {}).get('last_opened_file_path', '')
                log_text.insert(tk.END, f"修改前: last_opened_file_path={old_last_opened_file_path}\n")
    
                # 更新last_opened_file_path
                key_to_string_dict.setdefault('keyToString', {})['last_opened_file_path'] = new_last_opened_file_path
                log_text.insert(tk.END, f"修改后: last_opened_file_path={new_last_opened_file_path}\n")
    
                # 生成新的 JSON 数据
                # 保持原始 JSON 数据的格式
                new_key_to_string_json = json.dumps(key_to_string_dict, ensure_ascii=False, indent=None, separators=(',', ': '))
    
                # 构造新的CDATA内容
                new_cdata_content = "<![CDATA[" + new_key_to_string_json + "]]>"
    
                # 更新CDATA内容
                properties_component.text = new_cdata_content
    
                # 写回workspace.xml配置文件
                tree.write(workspace_xml_path, encoding='utf-8', xml_declaration=True, pretty_print=True)
    
                log_text.insert(tk.END, f"已更新或添加last_opened_file_path: {new_last_opened_file_path} 到 {workspace_xml_path}\n")
            except json.JSONDecodeError as e:
                log_text.insert(tk.END, f"JSON 解析错误: {e}\n")
            except Exception as e:
                log_text.insert(tk.END, f"处理配置文件 {workspace_xml_path} 失败: {e}\n")
    import re
    import os
    import tkinter as tk
    from tkinter import messagebox
    
    # 更新workspace.xml配置文件
    def on_workspace_xml_update():
        directory = search_entry.get().strip()
        if not directory:
            directory = os.getcwd()
    
        # 获取新的 last_opened_file_path
        new_last_opened_file_path = new_last_opened_file_path_entry.get().strip()
        if not new_last_opened_file_path:
            #messagebox.showerror("错误", "新的last_opened_file_path不能为空")
            status_label.config(text=f"新的last_opened_file_path不能为空")
            return
    
        # 确保路径使用正斜杠
        new_last_opened_file_path = new_last_opened_file_path.replace("\\", "/")
    
        # 查找workspace.xml配置文件
        found_files = []
        for root, dirs, files in os.walk(directory):
            for file in files:
                if file.lower() == 'workspace.xml':
                    found_files.append(os.path.join(root, file))
    
        if not found_files:
            messagebox.showinfo("信息", "没有找到workspace.xml配置文件")
            return
    
        for workspace_xml_path in found_files:
            # 读取配置文件内容
            with open(workspace_xml_path, 'r', encoding='utf-8') as file:
                content = file.read()
    
            # 查找包含 "last_opened_file_path" 的 JSON 字符串
            pattern = r'"last_opened_file_path"\s*:\s*"([^"]+)"'
            match = re.search(pattern, content)
    
            if match:
                # 替换 "last_opened_file_path" 的值
                old_value = match.group(1)
                content = re.sub(pattern, f'"last_opened_file_path": "{new_last_opened_file_path}"', content)
    
                # 写回配置文件
                with open(workspace_xml_path, 'w', encoding='utf-8') as file:
                    file.write(content)
    
                log_text.insert(tk.END, f"已将 {old_value} 替换为 {new_last_opened_file_path} 在 {workspace_xml_path}\n")
            else:
                log_text.insert(tk.END, f"未找到 last_opened_file_path 在 {workspace_xml_path}\n")
    
    
    
    
    
    import tkinter as tk
    from tkinter import scrolledtext
    import tkinter.font as tkFont
    import os
    import re
    
    # RGB值
    background_rgb = (43, 42, 51)
    output_bg_rgb = (31, 31, 31)
    output_fg_rgb = (255, 255, 255)  # 白色
    button_bg_rgb = (31, 31, 31)  # 按钮背景颜色
    button_fg_rgb = (0, 128, 0)  # 按钮文本颜色
    entry_bg_rgb = (31, 31, 31)  # 输入框背景颜色
    entry_fg_rgb = (255, 255, 255)  # 输入框文本颜色
    label_bg_rgb = (43, 42, 51)  # 标签背景颜色
    label_fg_rgb = (255, 255, 255)  # 标签文本颜色
    
    # 辅助函数
    def create_label(parent, text, **kwargs):
        return tk.Label(
            parent,
            text=text,
            font=large_font,
            fg=f"#{label_fg_rgb[0]:02X}{label_fg_rgb[1]:02X}{label_fg_rgb[2]:02X}",
            bg=f"#{label_bg_rgb[0]:02X}{label_bg_rgb[1]:02X}{label_bg_rgb[2]:02X}",
            **kwargs
        )
    
    def create_entry(parent, **kwargs):
        return tk.Entry(
            parent,
            font=large_font,
            fg=f"#{entry_fg_rgb[0]:02X}{entry_fg_rgb[1]:02X}{entry_fg_rgb[2]:02X}",
            bg=f"#{entry_bg_rgb[0]:02X}{entry_bg_rgb[1]:02X}{entry_bg_rgb[2]:02X}",
            **kwargs
        )
    
    def create_button(parent, text, command, **kwargs):
        return tk.Button(
            parent,
            text=text,
            font=large_font,
            fg=f"#{button_fg_rgb[0]:02X}{button_fg_rgb[1]:02X}{button_fg_rgb[2]:02X}",
            bg=f"#{button_bg_rgb[0]:02X}{button_bg_rgb[1]:02X}{button_bg_rgb[2]:02X}",
            command=command,
            **kwargs
        )
    
    # 日志记录
    def log(message):
        log_text.insert(tk.END, message + "\n")
        log_text.see(tk.END)  # 自动滚动到底部
    # 创建主窗口
    root = tk.Tk()
    # 定义一个更大的字体(不加粗)
    large_font = tkFont.Font(family="宋体", size=13)  # 调整字体大小,但不加粗
    root.title("修改android-studio项目配置JDK路径和项目gradle路径")
    #root.title("Config Properties & Workspace XML Editor")
    
    # 设置背景颜色
    root.configure(bg=f"#{background_rgb[0]:02X}{background_rgb[1]:02X}{background_rgb[2]:02X}")
    
    # 定义一个更大的字体(不加粗)
    large_font = tkFont.Font(family="宋体", size=13)  # 调整字体大小,但不加粗
    
    # 创建GUI组件
    create_label(root, "请输入目录路径 (留空则使用当前路径),搜索config.properties中java.home值").pack(pady=5)
    search_entry = create_entry(root, width=50)
    search_entry.pack(pady=5)
    
    # 搜索config.properties按钮
    search_button = create_button(root, "搜索android-studio项目配置JDK路径", on_search)
    search_button.pack(pady=5)
    
    # 输入新的java.home值
    create_label(root, "请输入新的java.home值=android-studio项目自定义配置JDK路径").pack(pady=9)
    entry_new_value = create_entry(root, width=50)
    entry_new_value.pack(pady=5)
    
    # 更新config.properties按钮
    update_button = create_button(root, "更新android-studio配置JDK路径", on_update)
    update_button.pack(pady=5)
    
    # 分隔符
    tk.Frame(height=2, bd=1, relief=tk.SUNKEN).pack(fill=tk.X, padx=5, pady=5)
    
    # 搜索workspace.xml按钮
    workspace_xml_search_button = create_button(root, "搜索workspace.xml", on_workspace_xml_search)
    workspace_xml_search_button.pack(pady=5)
    
    # 输入新的last_opened_file_path
    create_label(root, "请输入新的last_opened_file_path=你的android-studio的gradle路径").pack(pady=5)
    new_last_opened_file_path_entry = create_entry(root, width=50)
    new_last_opened_file_path_entry.pack(pady=5)
    
    # 更新workspace.xml按钮
    workspace_xml_update_button = create_button(root, "更新workspace.xml=配置android-studio项目的gradle路径", on_workspace_xml_update)
    workspace_xml_update_button.pack(pady=5)
    
    # 状态标签
    status_label = create_label(root, "")
    status_label.pack(pady=5)
    
    # 日志文本框
    log_text = scrolledtext.ScrolledText(
        root,
        width=80,
        height=20,
        wrap=tk.WORD,
        font=large_font,
        fg=f"#{output_fg_rgb[0]:02X}{output_fg_rgb[1]:02X}{output_fg_rgb[2]:02X}",
        bg=f"#{output_bg_rgb[0]:02X}{output_bg_rgb[1]:02X}{output_bg_rgb[2]:02X}"
    )
    log_text.pack(pady=5)
    
    # 运行主循环
    root.mainloop()
    复制代码

主窗口布局

  • 输入目录路径:用户可以在这里输入Android Studio项目的根目录路径。如果留空,则默认使用当前工作目录。
  • 搜索config.properties :点击此按钮将搜索指定目录下的config.properties文件,并显示当前的java.home值。
  • 输入新的java.home:用户可以在此输入新的JDK路径。
  • 更新config.properties :点击此按钮将更新config.properties文件中的java.home值为用户指定的新路径。
  • 搜索workspace.xml :点击此按钮将搜索指定目录下的workspace.xml文件,并显示当前的last_opened_file_path值。
  • 输入新的last_opened_file_path:用户可以在此输入新的Gradle路径。
  • 更新workspace.xml :点击此按钮将更新workspace.xml文件中的last_opened_file_path值为用户指定的新路径。
  • 日志文本框:显示操作过程中的信息和结果。

使用步骤

  1. 启动程序 :运行config_editor.py后,会弹出一个窗口。
  2. 输入目录路径(可选):在"请输入目录路径 (留空则使用当前路径)"输入框中输入Android Studio项目的根目录路径。如果留空,则默认使用当前工作目录。
  3. 搜索config.properties :点击"搜索android-studio项目配置JDK路径"按钮。程序会在指定目录下查找config.properties文件,并显示当前的java.home值。
  4. 更新java.home
    • 在"请输入新的java.home值"输入框中输入新的JDK路径。
    • 点击"更新android-studio配置JDK路径"按钮,程序会更新config.properties文件中的java.home值。
  5. 搜索workspace.xml :点击"搜索workspace.xml"按钮。程序会在指定目录下查找workspace.xml文件,并显示当前的last_opened_file_path值。
  6. 更新last_opened_file_path
    • 在"请输入新的last_opened_file_path"输入框中输入新的Gradle路径。
    • 点击"更新workspace.xml=配置android-studio项目的gradle路径"按钮,程序会更新workspace.xml文件中的last_opened_file_path值。
  7. 查看日志:所有操作的结果都会显示在日志文本框中,包括成功消息和错误信息。

注意事项

  • 确保你有足够的权限来读取和写入指定的文件。
  • 在更新配置文件之前,请备份原始文件,以防意外发生。
  • 请确保输入的路径是正确的,并且路径存在。
  • 如果路径或文件名包含特殊字符,请确保它们被正确转义或引用。

通过以上步骤,你可以轻松地管理和更新Android Studio项目的配置文件,从而确保项目使用的JDK和Gradle路径是正确的。希望这个工具能帮助你提高开发效率!

相关推荐
不务专业的程序员--阿飞4 分钟前
【SQL 如何解锁递归】
java·数据库·sql
嘵奇10 分钟前
Spring Boot拦截器详解:原理、实现与应用场景
java·spring boot·后端
八股文领域大手子11 分钟前
Java死锁排查:线上救火实战指南
java·开发语言·面试
jackson凌18 分钟前
【Java学习笔记】finalize方法
java·笔记·学习
fanTuanye21 分钟前
redis 缓存穿透,缓存击穿,缓存雪崩
java·redis·缓存
神秘的t38 分钟前
Spring Web MVC————入门(2)
java·spring·mvc
开开心心就好1 小时前
高效全能PDF工具,支持OCR识别
java·前端·python·pdf·ocr·maven·jetty
冷心笑看丽美人1 小时前
Spring MVC数据绑定和响应 你了解多少?
java·spring·mvc
XQ丶YTY1 小时前
大二java第一面小厂(挂)
java·开发语言·笔记·学习·面试
一零贰肆1 小时前
深入理解SpringBoot中的SpringCache缓存技术
java·springboot·springcache·缓存技术