diff --git a/README.md b/README.md index 7c65943..f69642b 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,10 @@ # 安卓sdk工具 #### 介绍 -用于安卓sdk做热更新常用的一些工具 +用于工作上安卓sdk做热更新常用的一些工具 -#### 软件架构 -软件架构说明 - - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx #### 使用说明 -1. xxxx -2. xxxx -3. xxxx +1. 要用签名工具则必须配好jarsigner环境 -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request - - -#### 码云特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 -5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/src/com/qy/Interfaces/DalogAbs.java b/src/com/qy/Interfaces/DalogAbs.java deleted file mode 100755 index 0047e93..0000000 --- a/src/com/qy/Interfaces/DalogAbs.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.qy.Interfaces; - -public abstract class DalogAbs { - public abstract void onSuccess(); -} diff --git a/src/com/qy/Interfaces/DialogInterface.java b/src/com/qy/Interfaces/DialogInterface.java new file mode 100644 index 0000000..b0b6c71 --- /dev/null +++ b/src/com/qy/Interfaces/DialogInterface.java @@ -0,0 +1,6 @@ +package com.qy.Interfaces; + +public abstract class DialogInterface { + public void onSuccess(){}; + public void onOut(Object data){}; +} diff --git a/src/com/qy/ui/AppMain.java b/src/com/qy/ui/AppMain.java index 37982a5..d658f87 100755 --- a/src/com/qy/ui/AppMain.java +++ b/src/com/qy/ui/AppMain.java @@ -223,7 +223,7 @@ public class AppMain extends JFrame { // TODO: handle exception e.printStackTrace(); } - setTitle("\u8F6C\u6362\u5668v2.10"); + setTitle("\u8F6C\u6362\u5668v2.2"); // TODO Auto-generated constructor stub setSize(900, 456); getContentPane().setLayout(null); @@ -653,6 +653,16 @@ public class AppMain extends JFrame { }); menu.add(autoSDK); + JMenuItem autoOutApk = new JMenuItem("自动更新SDK"); + autoOutApk.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + new AutoOutAPKUi(); + } + }); + menu.add(autoOutApk); + + mnBasetools = new JMenu("Base64\u5DE5\u5177"); menuBar.add(mnBasetools); diff --git a/src/com/qy/ui/AutoOutAPKAddChannelUi.form b/src/com/qy/ui/AutoOutAPKAddChannelUi.form new file mode 100644 index 0000000..da1b04a --- /dev/null +++ b/src/com/qy/ui/AutoOutAPKAddChannelUi.form @@ -0,0 +1,30 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/com/qy/ui/AutoOutAPKAddChannelUi.java b/src/com/qy/ui/AutoOutAPKAddChannelUi.java new file mode 100644 index 0000000..99e6254 --- /dev/null +++ b/src/com/qy/ui/AutoOutAPKAddChannelUi.java @@ -0,0 +1,99 @@ +package com.qy.ui; + +import com.qy.Interfaces.DialogInterface; +import com.qy.utils.Tools; +import org.json.JSONArray; +import org.json.JSONObject; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.*; +import java.util.List; + +public class AutoOutAPKAddChannelUi { + private JComboBox comboBox1; + private JPanel panel1; + private JButton submit; + private JPanel inputPanel; + private JSONObject json; + private List list=new ArrayList<>(); + private DialogInterface inter; + private JFrame frame; + + public AutoOutAPKAddChannelUi(DialogInterface inter, JFrame frame) { + this.inter=inter; + this.frame=frame; + json= Tools.loadConfig(new File("gameConfig.json")); + init(); + } + private void init(){ + Vector vector=new Vector<>(json.keySet()); + comboBox1.setModel(new DefaultComboBoxModel<>(vector)); + comboBox1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setData(comboBox1.getSelectedIndex()); + } + }); + submit.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Map map=new HashMap<>(); + map.put("NAME",name); + for (JTextField textField : list) { + map.put(textField.getName(),textField.getText()); + } + inter.onOut(map); + AutoOutAPKAddChannelUi.this.frame.dispose(); + } + }); + GridLayout layout=new GridLayout(-1,1); + inputPanel.setLayout(layout); + inputPanel.setBackground(Color.black); + setData(0); + } + private String name=""; + private void setData(int index){ + inputPanel.removeAll(); + inputPanel.updateUI(); + list.clear(); + JSONArray item = null; + int i=0; + for (String key : json.keySet()) { + if(i==index){ + item=json.getJSONArray(key); + name=key; + break; + } + i++; + } + if(item==null){ + return; + } + for (int j = 0; j +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/com/qy/ui/AutoOutAPKUi.java b/src/com/qy/ui/AutoOutAPKUi.java new file mode 100644 index 0000000..a1425ef --- /dev/null +++ b/src/com/qy/ui/AutoOutAPKUi.java @@ -0,0 +1,177 @@ +package com.qy.ui; + +import com.qy.Interfaces.DialogInterface; +import com.qy.Interfaces.SmaliApkToolsPath; +import com.qy.utils.ApkSignTools; +import com.qy.utils.AutoOutAPKTools; +import com.qy.utils.Tools; +import org.apache.commons.lang3.StringUtils; +import org.json.JSONObject; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Vector; + +public class AutoOutAPKUi { + private JPanel panel1; + private JTextField packageName; + private JTextField gameId; + private JTextField jiguang; + private JList list1; + private JButton addChannel; + private JButton removeChannel; + private JButton start; + private JButton selectAppPath; + private JLabel appPath; + + private LinkedHashMap map = new LinkedHashMap<>(); + private LinkedHashMap channel = new LinkedHashMap<>(); + private Vector vector = new Vector(); + + + public AutoOutAPKUi() { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + // TODO: handle exception + e.printStackTrace(); + } + JFrame frame = new JFrame("马甲包出包工具1.0"); + frame.setContentPane(panel1); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.pack(); + frame.setSize(420, 400); + frame.setVisible(true); + initView(); + } + + private void initView() { + list1.setListData(vector); + addChannel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + AutoOutAPKAddChannelUi.newInstance(new DialogInterface() { + @Override + public void onOut(Object data) { + super.onOut(data); + Map channel = (Map) data; + AutoOutAPKUi.this.channel.put((String) channel.get("NAME"), channel); + vector.add((String) channel.get("NAME")); + list1.setListData(vector); + list1.updateUI(); + } + }); + + } + }); + removeChannel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String name = vector.get(list1.getSelectedIndex()); + vector.remove(list1.getSelectedIndex()); + channel.remove(name); + list1.setListData(vector); + list1.updateUI(); + } + }); + start.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String gid = gameId.getText(); + String jid = jiguang.getText(); + String pid = packageName.getText(); + String path = appPath.getText(); + if (StringUtils.isEmpty(gid) || StringUtils.isEmpty(pid) || StringUtils.isEmpty(path)) { + new TextToDialog("警告", "有参数未填写"); + return; + } + Map cmap = new HashMap<>(); + for (String key : channel.keySet()) { + Map map = (Map) channel.get(key); + for (Object o : map.keySet()) { + if (!o.equals("NAME")) { + cmap.put((String) o, (String) map.get(o)); + } + } + } + AutoOutAPKTools tools = new AutoOutAPKTools(gid, cmap); + JSONObject json=new JSONObject(); + JSONObject pa=new JSONObject(); + JSONObject ji=new JSONObject(); + pa.put("key","${packagename}"); + pa.put("value",pid); + ji.put("key","${JPUSH_KEY}"); + ji.put("value",jid); + json.put("package=",pa); + json.put("JPUSH_APPKEY",ji); + tools.setAppPath(path); + tools.setManifestMap(json); + tools.start(new SmaliApkToolsPath() { + @Override + public void smaliPath(String path) { + LinkedHashMap keyMap=ApkSignUi.loadKeys(); + Vector adbList = new Vector(keyMap.keySet()); + JComboBox keysList=new JComboBox(adbList); + keysList.setBounds(157, 50, 200, 27); + new TextToDialog("选择签名", keysList, new DialogInterface() { + @Override + public void onSuccess() { + String key=adbList.get(keysList.getSelectedIndex()); + String tmp=keyMap.get(key); + if(!StringUtils.isEmpty(tmp)){ + JSONObject json=new JSONObject(tmp); + ApkSignTools signTools=new ApkSignTools(); + signTools.setSignFile(new File(json.getString("file"))); + signTools.setApkFile(new File(path)); + signTools.setKeyStorePassword(json.getString("alias_password")); + signTools.setName(json.getString("alias")); + signTools.setSignKey(json.getString("password")); + if(signTools.sign()){ + try { + String apkName="./apk_out/game_"+System.currentTimeMillis()+".apk"; + Tools.copyFile(signTools.getApkFile().getAbsolutePath()+"_sign.apk",apkName,true); + Desktop.getDesktop().open(new File(apkName).getParentFile()); + System.out.println("签名完成"); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + tools.clear(); + }else { + new TextToDialog("警告","签名失败"); + } + } + } + }); + } + }); + } + }); + + selectAppPath.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser jFile = new JFileChooser(new File(new File("").getAbsolutePath())); + jFile.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + jFile.showOpenDialog(null); + File path = jFile.getSelectedFile(); + appPath.setText(path.getAbsolutePath()); + } + }); + } + + private void createUIComponents() { + // TODO: place custom component creation code here + } + + + public static void main(String[] args) { + new AutoOutAPKUi(); + } +} diff --git a/src/com/qy/ui/SMSToolsUi.java b/src/com/qy/ui/SMSToolsUi.java index ec3f81d..0594531 100755 --- a/src/com/qy/ui/SMSToolsUi.java +++ b/src/com/qy/ui/SMSToolsUi.java @@ -11,7 +11,7 @@ import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.UIManager; -import com.qy.Interfaces.DalogAbs; +import com.qy.Interfaces.DialogInterface; import com.qy.sms.SDKTools; import java.awt.Desktop; @@ -71,7 +71,7 @@ public class SMSToolsUi extends JFrame { SDKTools.start(new File("").getAbsolutePath()); btnNewButton.setText(path); btnNewButton.setEnabled(true); - new TextToDialog("提示", "计费SDK生成成功,请选择保存位置", new DalogAbs() { + new TextToDialog("提示", "计费SDK生成成功,请选择保存位置", new DialogInterface() { File sdk; @Override @@ -85,7 +85,7 @@ public class SMSToolsUi extends JFrame { File sdk_ = new File( sdk.getAbsolutePath() + "/" + "计费sdk" + SDKTools.version + ".zip"); SDKTools.buildSDK(sdk_); - new TextToDialog("完成", "任务已完成", new DalogAbs() { + new TextToDialog("完成", "任务已完成", new DialogInterface() { @Override public void onSuccess() { diff --git a/src/com/qy/ui/SmaliUi.java b/src/com/qy/ui/SmaliUi.java index 2cd2b6c..041e929 100755 --- a/src/com/qy/ui/SmaliUi.java +++ b/src/com/qy/ui/SmaliUi.java @@ -16,7 +16,7 @@ import javax.swing.border.LineBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import com.qy.Interfaces.DalogAbs; +import com.qy.Interfaces.DialogInterface; import com.qy.Interfaces.SmaliApkToolsPath; import com.qy.utils.ApkSignTools; import com.qy.utils.SmaliUtils; @@ -361,7 +361,7 @@ public class SmaliUi extends JFrame { Vector adbList = new Vector(keyMap.keySet()); JComboBox keysList=new JComboBox(adbList); keysList.setBounds(157, 50, 200, 27); - new TextToDialog("选择签名", keysList, new DalogAbs() { + new TextToDialog("选择签名", keysList, new DialogInterface() { @Override public void onSuccess() { String key=adbList.get(keysList.getSelectedIndex()); diff --git a/src/com/qy/ui/TextToDialog.java b/src/com/qy/ui/TextToDialog.java index f5676ad..a2e6d08 100644 --- a/src/com/qy/ui/TextToDialog.java +++ b/src/com/qy/ui/TextToDialog.java @@ -5,22 +5,22 @@ import java.awt.event.MouseEvent; import javax.swing.*; -import com.qy.Interfaces.DalogAbs; +import com.qy.Interfaces.DialogInterface; public class TextToDialog extends JFrame { /** * */ - DalogAbs abs; + DialogInterface abs; private static final long serialVersionUID = 1L; - public TextToDialog(String title, String text, DalogAbs abs) { + public TextToDialog(String title, String text, DialogInterface abs) { super(title); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.abs=abs; initView(text,null); } - public TextToDialog(String title, JComponent view,DalogAbs abs){ + public TextToDialog(String title, JComponent view, DialogInterface abs){ super(title); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.abs=abs; diff --git a/src/com/qy/utils/ApkSignTools.java b/src/com/qy/utils/ApkSignTools.java index 7630c4e..b5970a2 100644 --- a/src/com/qy/utils/ApkSignTools.java +++ b/src/com/qy/utils/ApkSignTools.java @@ -74,6 +74,7 @@ public class ApkSignTools { } public void setApkFile(File apkFile) { this.apkFile = apkFile; + System.out.println("APK:"+apkFile.getAbsolutePath()); } public boolean chack() { // TODO Auto-generated method stub diff --git a/src/com/qy/utils/AutoOutAPKTools.java b/src/com/qy/utils/AutoOutAPKTools.java new file mode 100644 index 0000000..44869bd --- /dev/null +++ b/src/com/qy/utils/AutoOutAPKTools.java @@ -0,0 +1,116 @@ +package com.qy.utils; + +import com.qy.Interfaces.SmaliApkToolsPath; +import com.qy.ui.ApkSignUi; +import org.json.JSONObject; + +import javax.swing.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.*; + +public class AutoOutAPKTools { + private String gameId; + private Map channel; + private JSONObject manifestMap; + private String appPath; + private SmaliApkToolsPath inter; + + public AutoOutAPKTools(String gameId, Map channel) { + this.gameId = gameId; + this.channel = channel; + } + public void setAppPath(String path){ + this.appPath=path; + } + public void setManifestMap(JSONObject map){ + this.manifestMap=map; + } + public void start(SmaliApkToolsPath inter){ + this.inter=inter; + outLog("复制游戏文件夹"); + String newAppPath=appPath+"_"+gameId+"_"+Tools.getRandomString(6); + Tools.copy_dir(appPath,newAppPath); + outLog("游戏游戏文件夹复制完成"); + appPath=newAppPath; + outLog("修改Manifest"); + alterManifest(new File(appPath+File.separator+"AndroidManifest.xml")); + outLog("Manifest修改完成,开始生成assets"); + outAssets(); + outLog("生成完毕"); + new SmaliUtils().bale(appPath, appPath + File.separator + "game_.apk", new SmaliApkToolsPath() { + @Override + public void smaliPath(String path) { + inter.smaliPath(appPath + File.separator + "game_.apk"); + } + }); + } + public void clear(){ + Tools.deleteFiles(appPath); + } + private void alterManifest(File manifest){ + String tmp; + StringBuilder str = new StringBuilder(); + try { + List keys=new ArrayList<>(manifestMap.keySet()); + + BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(manifest), StandardCharsets.UTF_8)); + while ((tmp = reader.readLine()) != null) { + for (String key : keys) { + if(tmp.contains(key)){ + JSONObject json=manifestMap.getJSONObject(key); + tmp=tmp.replace(json.getString("key"),json.getString("value")); + } + } + str.append(tmp).append("\n"); + } + reader.close(); + Tools.saveConfig(manifest,str.toString()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + System.out.println(str); + } + } + private void outAssets(){ + StringBuilder builder=new StringBuilder(); + builder.append("GAME_ID=").append(gameId).append("\n"); + for (String key : channel.keySet()) { + builder.append(key).append("=").append(channel.get(key)).append("\n"); + } + Tools.saveConfig(new File(appPath+File.separator+"assets"+File.separator+"kusdkconf.ini"), + builder.toString()); + } + private void outLog(String log){ + System.out.println(log); + } + + public static void main(String[] args) { + JSONObject json=new JSONObject(); + JSONObject pa=new JSONObject(); + JSONObject ji=new JSONObject(); + pa.put("key","${packagename}"); + pa.put("value","com.abc.def"); + ji.put("key","${JPUSH_KEY}"); + ji.put("value","aaabbccd"); + json.put("package=",pa); + json.put("JPUSH_APPKEY",ji); + + Map channel=new HashMap<>(); + channel.put("TOUTIAO_APP_ID","112345"); + AutoOutAPKTools tools=new AutoOutAPKTools( + "123456", + channel); + tools.setAppPath("C:\\Users\\admin\\Documents\\游戏母包\\仙侠神域\\xianxiashenyu_29321_wozaijianghukey_xxsy_1627"); + tools.setManifestMap(json); + tools.start(new SmaliApkToolsPath() { + @Override + public void smaliPath(String path) { + System.out.println("ok:"+path); + } + }); + } +} diff --git a/src/com/qy/utils/Tools.java b/src/com/qy/utils/Tools.java index 1ac3870..17af3ab 100755 --- a/src/com/qy/utils/Tools.java +++ b/src/com/qy/utils/Tools.java @@ -365,4 +365,21 @@ public class Tools { System.out.println(System.getProperties().getProperty("os.name")); return System.getProperties().getProperty("os.name").toLowerCase().contains("windows"); } + + public static String readFile(File manifest) { + String tmp; + StringBuilder str = new StringBuilder(); + try { + BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(manifest), StandardCharsets.UTF_8)); + while ((tmp = reader.readLine()) != null) { + str.append(tmp); + } + reader.close(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + System.out.println(str); + } + return str.toString(); + } }