打包是程序员必经之路。如何实现自动化是一个程序员的基本素质。(都是因为我懒,哈哈哈)。
使用环境 :unity3D 2017.4.7 Mac Pro
打包分一下几个部分 :
1、unity3D导出xcode 工程
2、设置xcode配置及各种sdk配置
3、命令行打包
4、上传蒲公英
5、上传bugly
【IOS自动化解放双手系列一】unity3D导出xcode 工程并配置各种权限
【IOS自动化解放双手系列二】命令行打IPA包和上传蒲公英
【IOS自动化解放双手系列三】上传bugly
接下来开始正式看代码

1、unity3D导出xcode 工程
我们使用assetbundle打包所以需要先打ab包 让配置相关服务器文件,在进行导出 代码如下

   public enum BUILDTYPE {QA,PREFE,REALSE}private static BUILDTYPE currenBulidType = BUILDTYPE.REALSE;public static void ExportIOSProject(BUILDTYPE uILDTYPE) {currenBulidType = uILDTYPE;EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.iOS, BuildTarget.iOS);AssetDatabase.Refresh();MoveGameConfig(uILDTYPE);string shellPath = Application.dataPath.Replace("Assets", "Build/iOS/");//step1.打包资源。通过AssetBundleGraph 生成Build AssetsBundlesBuildAssetsBundles();UnityEngine.Debug.Log("step1 Finished!!!");//Step2.移除无关文件,为Export IOS 工程做准备,调用shell脚本RunShell(shellPath + "RemoveFromUnity.sh");AssetDatabase.Refresh();UnityEngine.Debug.Log("step2 Finished!!!");//Step3.导出Apple 真机工程ExportAppleProject(iOSSdkVersion.DeviceSDK);UnityEngine.Debug.Log("step3 Finished!!!");//Step4.删除临时文件,调用shell脚本RunShell(shellPath + "RecoverUnity.sh");UnityEngine.Debug.Log("step4 Finished!!!");PlayerSettings.applicationIdentifier = "com.XXXX.XXX";AssetDatabase.Refresh();}public static void ExportAppleProject(iOSSdkVersion sdk) {List<string> scenes = new List<string>();foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes) {if (!scene.enabled)continue;scenes.Add(scene.path);}bool isQA = false;switch (currenBulidType) {case BUILDTYPE.QA:case BUILDTYPE.PREFE:isQA = true;PlayerSettings.applicationIdentifier = "com.XXXX.XXX";break;case BUILDTYPE.REALSE:PlayerSettings.applicationIdentifier = "com.XXXX.XXX";isQA = false;break;}EditorUserBuildSettings.development = isQA;PlayerSettings.iOS.sdkVersion = sdk;PlayerSettings.iOS.buildNumber = GetVersion().ToString();//EditorUserBuildSettings.targetBuildOptions buildOption = BuildOptions.None;string res = BuildPipeline.BuildPlayer(scenes.ToArray(), PathUtils.CombinePath("Build", ToolsFunctions.GetPlatformDefines(), "Project", sdk.ToString()), BuildTarget.iOS, buildOption);if (res.Length > 0) {throw new Exception("BuildPlayer failure : " + res);}}//=====================================公共函数=======================================private static void BuildAssetsBundles() {UnityEngine.AssetBundles.GraphTool.BatchBuildWindow.Open();UnityEngine.AssetBundles.GraphTool.BatchBuildWindow.BuildFromMenu();}private static void RunShell(string shellFile) {//      Thread thread = new Thread(new )//为了可以重试多线程所以加了一层UnityRunShell(shellFile);}private static void UnityRunShell(string shellFile) {Process process = new Process();process.StartInfo.FileName = shellFile;//      process.StartInfo.Arguments = "";process.StartInfo.UseShellExecute = false;process.StartInfo.ErrorDialog = true;process.StartInfo.CreateNoWindow = false;process.Start();process.WaitForExit();process.Close();}private static int GetVersion(){return ClientVersion.GetIncrementBundleVersion();}private static void MoveGameConfig(BUILDTYPE uILDTYPE ){string path = PathUtils.CombinePath(Application.dataPath,"../GameConfig/gameRealse.xml");switch(uILDTYPE){case BUILDTYPE.QA:path = PathUtils.CombinePath(Application.dataPath,"../GameConfig/gameQA.xml");break;case BUILDTYPE.PREFE:path = PathUtils.CombinePath(Application.dataPath,"../GameConfig/gamePrefe.xml");break;case BUILDTYPE.REALSE:path = PathUtils.CombinePath(Application.dataPath,"../GameConfig/gameRealse.xml");break;}CopyConfig(path);}private static void CopyConfig(string path) {string targePath = PathUtils.CombinePath(PathUtils.GameConfigWWWPath, "game.xml");string configStr = FileUtils.ReadAllText(path);if (string.IsNullOrEmpty(configStr)) {Client.LogManager.LogError("配置信息有误请查看后重新写入");}FileUtils.WriteAllText(targePath, configStr);Client.LogManager.Log("copy GameConfig finish");}

2、设置xcode配置及各种sdk配置
分一下几部分:
添加类库
框架的搜索追加设置
设置推送权限配置XXXXX.entitlements文件
unity修改oc代码

#if (UNITY_IOS || UNITY_IPHONE)
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using System.Linq;
using System.Diagnostics;
using CDBGUnity;public class CDBGPluginBuilder : MonoBehaviour {public static bool isUseTestXG = false;public static bool enableIosAppController = true;[PostProcessBuildAttribute(6)]static void onPostProcessBuild(BuildTarget buildTarget, string path) {UnityEngine.Debug.Log("PostProcessBuild   Start");if (buildTarget == BuildTarget.iOS) {// project pathstring projectPath = Path.Combine(path, "Unity-iPhone.xcodeproj/project.pbxproj");// xcodeprojPBXProject proj = new PBXProject();proj.ReadFromString(File.ReadAllText(projectPath));// targetstring target = PBXProject.GetUnityTargetName();target = proj.TargetGuidByName(target);UnityEngine.Debug.Log(">>>>target: " + target + "path :" + path);// Add System Frameworks//UnityEngine.Debug.Log(">>>>>Adding system frameworks to xcodeproj...");//proj.AddFrameworkToProject(target, "CoreText.framework", false);//proj.AddFrameworkToProject(target, "MediaPlayer.framework", false);proj.AddFrameworkToProject(target,"AgoraSigKit.framework",false);// Macro //proj.AddBuildProperty(target, "GCC_PREPROCESSOR_DEFINITIONS", "");// 信鸽相关//string[] macros = { "USE_TestXG=1" };//if (isUseTestXG) {//    UnityEngine.Debug.Log("Enabling USE_TestXG...");//    proj.UpdateBuildProperty(target, "GCC_PREPROCESSOR_DEFINITIONS", macros, null);//} else {//    UnityEngine.Debug.Log("Disabling USE_TestXG...");//    proj.UpdateBuildProperty(target, "GCC_PREPROCESSOR_DEFINITIONS", null, macros);//}//proj.AddBuildProperty(target, "GCC_PREPROCESSOR_DEFINITIONS", "");//macros[0] = "USE_LGCAppController=1";//if (enableIosAppController) {//    UnityEngine.Debug.Log("Enabling USE_LGCAppController...");//    proj.UpdateBuildProperty(target, "GCC_PREPROCESSOR_DEFINITIONS", macros, null);//} else {//    UnityEngine.Debug.Log("Disabling USE_LGCAppController...");//    proj.UpdateBuildProperty(target, "GCC_PREPROCESSOR_DEFINITIONS", null, macros);//}//UnityEngine.Debug.Log("Setting up linker flags...");//string[] linkerFlagsToAdd = { "-ObjC", "-force_load", "$(PROJECT_DIR)/Frameworks/Plugins/iOS/LongtuSDK/LTShareSDK.framework/LTShareSDK" };//proj.UpdateBuildProperty(target, "OTHER_LDFLAGS", linkerFlagsToAdd, null);设置报名 //if (isUseTestXG) {//    proj.SetBuildProperty(target, "CODE_SIGN_IDENTITY", "iPhone Developer: jin dingjun (M39LLSEB5V)");//    proj.SetBuildProperty(target, "PROVISIONING_PROFILE", "xxaxc_cj_dev_20170609");//} else {//    proj.SetBuildProperty(target, "CODE_SIGN_IDENTITY", "iPhone Distribution: Beijing Zhong Qing Long Tu Network Technology Co.,LTD. (UC3LC49W33)");//    proj.SetBuildProperty(target, "PROVISIONING_PROFILE", "xxaxc_dist_20170607");//}//proj.overwriteBuildSetting ("CODE_SIGN_IDENTITY", "iPhone Developer: Yu Song (XXXXXXXXXX)", "Release");//proj.overwriteBuildSetting ("CODE_SIGN_IDENTITY", "iPhone Developer: Yu Song (XXXXXXXXXX)", "Debug");/****** Game End**///UnityEngine.Debug.Log(">>>>target :" + target + "path :" + path);// 框架的搜索追加设置XXXXX.entitlements//UnityEngine.Debug.Log(">>>>>LONGTU Setting up framework search paths...");//proj.SetBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(inherited)");//proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Libraries/");//proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Frameworks/");//proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Frameworks/Plugins/iOS/");//proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Frameworks/Plugins/iOS/LongtuSDK/");//proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Frameworks/ArmorSDK/Plugins/iOS/");#if UNITY_5//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libiconv.2.tbd", "Frameworks/libiconv.2.tbd", PBXSourceTree.Sdk));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.tbd", "Frameworks/libsqlite3.tbd", PBXSourceTree.Sdk));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libstdc++.6.0.9.tbd", "Frameworks/libstdc++.6.0.9.tbd", PBXSourceTree.Sdk));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libz.1.tbd", "Frameworks/libz.1.tbd", PBXSourceTree.Sdk));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libxml2.2.tbd", "Frameworks/libxml2.2.tbd", PBXSourceTree.Sdk));//proj.AddFileToBuild(target,proj.AddFile("usr/lib/libsqlite3.0.tbd"     ,"Frameworks/libsqlite3.0.tbd"     ,PBXSourceTree.Sdk));//proj.AddFileToBuild(target,proj.AddFile("usr/lib/libz.tbd"         ,"Frameworks/libz.tbd"         ,PBXSourceTree.Sdk));//string libiconvDylibPath = proj.AddFile("usr/lib/libiconv.2.dylib", "Frameworks/libiconv.2.dylib", PBXSourceTree.Sdk);proj.AddFileToBuild(target, libiconvDylibPath);//proj.RemoveFileFromBuild(target, libiconvDylibPath);
#else//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libiconv.2.dylib", "Frameworks/libiconv.2.dylib", PBXSourceTree.Source));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.dylib", "Frameworks/libsqlite3.dylib", PBXSourceTree.Source));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libstdc++.6.0.9.dylib", "Frameworks/libstdc++.6.0.9.dylib", PBXSourceTree.Source));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libz.1.dylib", "Frameworks/libz.1.dylib", PBXSourceTree.Source));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libxml2.2.dylib", "Frameworks/libxml2.2.dylib", PBXSourceTree.Source));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libsqlite3.0.dylib", "Frameworks/libsqlite3.0.dylib", PBXSourceTree.Source));//proj.AddFileToBuild(target, proj.AddFile("usr/lib/libz.dylib", "Frameworks/libz.dylib", PBXSourceTree.Source));
#endif//proj.RemoveFile(proj.FindFileGuidByProjectPath("Libraries/Plugins/iOS/LGUnityiOSPlugin/LGCAppController.mm"));//proj.AddFileToBuildWithFlags(target,//                              proj.AddFile("Libraries/Plugins/iOS/LGUnityiOSPlugin/LGCAppController.mm",//                                            "Libraries/Plugins/iOS/LGUnityiOSPlugin/LGCAppController.mm",//                                            PBXSourceTree.Source),//                              "-fno-objc-arc");//proj.RemoveFile(proj.FindFileGuidByProjectPath("Libraries/Plugins/iOS/UnitySysFont.mm"));//proj.AddFileToBuildWithFlags(target,//proj.AddFile("Libraries/Plugins/iOS/UnitySysFont.mm",//              "Libraries/Plugins/iOS/UnitySysFont.mm",//              PBXSourceTree.Source),//"-fno-objc-arc");// 書き出しFile.WriteAllText(projectPath, proj.WriteToString());// Info.plistUnityEngine.Debug.Log(">>>>>>>>>>>> game Updating Info.plist...");UpdateInfoPlist(path);//#endifvar capManager = new ProjectCapabilityManager(projectPath, "XXXXX.entitlements", PBXProject.GetUnityTargetName());//创建设置Capability类capManager.AddPushNotifications(true);//设置Capability//capManager.AddGameCenter();capManager.AddInAppPurchase();capManager.WriteToFile();//写入文件保存//3、修改代码//读取UnityAppController.mm文件UnityEditor.XCodeEditor.XClass UnityAppController = new UnityEditor.XCodeEditor.XClass(path + "/Classes/UnityAppController.mm");//在指定代码后面增加一行代码UnityAppController.WriteBelow("#include \"PluginBase/AppDelegateListener.h\"", "\n#import \"GeTuiSdk.h\"");//个推获取device tokenstring adInitCds = "  // [ GTSdk ]:向个推服务器注册deviceToken \n  NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@\"<>\"]];\n token = [token stringByReplacingOccurrencesOfString: @\" \" withString: @\"\"]; \n [GeTuiSdk registerDeviceToken:token];";UnityAppController.WriteBelow("UnitySendDeviceToken(deviceToken);\n", adInitCds);//读取UnityAppController.mm文件UnityEditor.XCodeEditor.XClass Preprocessor = new UnityEditor.XCodeEditor.XClass(path + "/Classes/Preprocessor.h");Preprocessor.Replace("#define UNITY_USES_REMOTE_NOTIFICATIONS 0","#define UNITY_USES_REMOTE_NOTIFICATIONS 1");}}internal static void UpdateInfoPlist(string path) {var plist = PlistBuddyHelper.ForPlistFile(Path.Combine(path, "Info.plist"));// Bundle Identifier//plist.SetString("CFBundleIdentifier", PlayerSettings.applicationIdentifier);plist.SetBool("CFBundleAllowMixedLocalizations", true);plist.SetString("CFBundleDevelopmentRegion", "zh_CN");plist.SetString("CFBundleName", "XXXXXXX");plist.AddBool("NSAppTransportSecurity:NSAllowsArbitraryLoads", true);plist.AddString("NSPhotoLibraryUsageDescription", "需要您的同意,才能访问相册");//plist.AddString("NSMicrophoneUsageDescription", "需要您的同意,才能访问麦克风");plist.AddString("NSCameraUsageDescription", "需要您的同意,才能访问相机");plist.AddString("NSLocationWhenInUseUsageDescription","需要您的同意,才能访问位置");plist.AddBool("ITSAppUsesNonExemptEncryption",false);//LSApplicationQueriesSchemes//plist.AddArray("LSApplicationQueriesSchemes");//plist.AddString("LSApplicationQueriesSchemes:0", "mqq");////plist.AddString("LSApplicationQueriesSchemes:1", "mqqapi");////plist.AddString("LSApplicationQueriesSchemes:2", "mqqwpa");////plist.AddString("LSApplicationQueriesSchemes:3", "mqqbrowser");//plist.AddString("LSApplicationQueriesSchemes:4", "mttbrowser");//plist.AddString("LSApplicationQueriesSchemes:5", "mqqOpensdkSSoLogin");//plist.AddString("LSApplicationQueriesSchemes:6", "mqqopensdkapiV2");//plist.AddString("LSApplicationQueriesSchemes:7", "sinaweibo");//plist.AddString("LSApplicationQueriesSchemes:8", "sinaweibohd");//plist.AddString("LSApplicationQueriesSchemes:9", "weibosdk");//plist.AddString("LSApplicationQueriesSchemes:10", "weibosdk2.5");//plist.AddString("LSApplicationQueriesSchemes:11", "weixin");//plist.AddString("LSApplicationQueriesSchemes:12", "wtloginmqq2");//plist.AddString("LSApplicationQueriesSchemes:13", "mqqapiwallet");//plist.AddString("LSApplicationQueriesSchemes:14", "mqqopensdkapiV3");//plist.AddString("LSApplicationQueriesSchemes:15", "mqqapiwallet");//plist.AddString("LSApplicationQueriesSchemes:16", "wechat");//UIBackgroundModesplist.AddArray("UIBackgroundModes");plist.AddString("UIBackgroundModes:0", "remote-notification");plist.AddString("UIBackgroundModes:1","voip");plist.AddBool("UIPushNotifications", true);weixin//plist.AddDictionary("CFBundleURLTypes", "1");//plist.AddString("CFBundleURLTypes:1:CFBundleTypeRole", "Editor");//plist.AddArray("CFBundleURLTypes", "1", "CFBundleURLSchemes");//plist.AddString("CFBundleURLTypes:1:CFBundleURLSchemes:0", "wx3ff69cc81203b2e1");tencent//plist.AddDictionary("CFBundleURLTypes", "2");//plist.AddString("CFBundleURLTypes:2:CFBundleTypeRole", "Editor");//plist.AddString("CFBundleURLTypes:2:CFBundleURLName", "tencentopenapi");//plist.AddArray("CFBundleURLTypes", "2", "CFBundleURLSchemes");//plist.AddString("CFBundleURLTypes:2:CFBundleURLSchemes:0", "tencent1106067576");weibo//plist.AddDictionary("CFBundleURLTypes", "3");//plist.AddString("CFBundleURLTypes:3:CFBundleTypeRole", "Editor");//plist.AddString("CFBundleURLTypes:3:CFBundleURLName", "com.weibo");//plist.AddArray("CFBundleURLTypes", "3", "CFBundleURLSchemes");//plist.AddString("CFBundleURLTypes:3:CFBundleURLSchemes:0", "wb2888694102");UnityEngine.Debug.Log(">>>>>>>>>>>>> Game Update Info Plist end");}internal static void AddDirectoryToXcodeproj(PBXProject proj, string targetGuid, string projectPath, string path, bool addSubDir = true) {UnityEngine.Debug.Log(">>>>> Game Adding to xcodeproj projectPath: " + projectPath + " path :" + path);string fullPath = Path.Combine(projectPath, path);UnityEngine.Debug.Log("fullPath:" + fullPath);if (Directory.Exists(fullPath)) {foreach (var file in Directory.GetFiles(fullPath)) {if (file.EndsWith(".meta")) continue;string filePath = Path.Combine(path, Path.GetFileName(file));UnityEngine.Debug.Log(">>>>> Game Adding to xcodeproj: " + filePath);proj.AddFileToBuild(targetGuid, proj.AddFile(filePath, filePath, PBXSourceTree.Source));}if (!addSubDir) {return;}foreach (var dir in Directory.GetDirectories(fullPath)) {string dirPath = Path.Combine(path, Path.GetFileName(dir));UnityEngine.Debug.Log(">>>> Game Adding dirPath to xcodeproj: " + dirPath);proj.AddFileToBuild(targetGuid, proj.AddFile(dirPath, dirPath, PBXSourceTree.Source));}} else {UnityEngine.Debug.LogWarning(">>>>Directory doesn't exist: " + fullPath);}}internal static void CopyDirectory(string srcPath, string dstPath) {using (var process = new Process()) {process.StartInfo.FileName = "/bin/cp";process.StartInfo.Arguments = string.Format("-Rf \"{0}\" \"{1}\"", srcPath, dstPath);UnityEngine.Debug.Log("Executing cp command: " + process.StartInfo.Arguments);process.StartInfo.CreateNoWindow = true;process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;process.StartInfo.UseShellExecute = false;process.StartInfo.RedirectStandardError = true;process.StartInfo.RedirectStandardOutput = true;try {process.Start();process.StandardError.ReadToEnd();var stdError = process.StandardError.ReadToEnd();if (stdError.Trim().Length > 0) {UnityEngine.Debug.Log("cp stderr: " + stdError);}if (!process.WaitForExit(10 * 1000)) {throw new Exception("cp did not exit in a timely fashion");}if (process.ExitCode != 0) {return;}return;} catch (Exception e) {throw new Exception("Encountered unexpected error while cp files.", e);}}}internal static void MoveItem(string srcPath, string dstPath) {using (var process = new Process()) {process.StartInfo.FileName = "/bin/mv";process.StartInfo.Arguments = string.Format("\"{0}\" \"{1}\"", srcPath, dstPath);UnityEngine.Debug.Log("Executing mv command: " + process.StartInfo.Arguments);process.StartInfo.CreateNoWindow = true;process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;process.StartInfo.UseShellExecute = false;process.StartInfo.RedirectStandardError = true;process.StartInfo.RedirectStandardOutput = true;try {process.Start();process.StandardError.ReadToEnd();var stdError = process.StandardError.ReadToEnd();if (stdError.Trim().Length > 0) {UnityEngine.Debug.Log("mv stderr: " + stdError);}if (!process.WaitForExit(10 * 1000)) {throw new Exception("mv did not exit in a timely fashion");}if (process.ExitCode != 0) {return;}return;} catch (Exception e) {throw new Exception("Encountered unexpected error while cp files.", e);}}}
}#endif

【IOS自动化解放双手系列一】unity3D导出xcode 工程并配置各种权限相关推荐

  1. unity导出XCode工程

    1.切换到ios平台 2.修改unity的PlayerSetting 打开PlayerSetting,修改部分设置.其中BundelIdentifier和Version根据实际情况填写即可. 3.导出 ...

  2. python xlwings 切片_python + xlwings 解放双手系列(1) 入门

    背景:孩子妈工作需要,每次都需要手动复制大量excel文件,可用python代码来解放双手 目录:python获得指定文件夹下所有文件路径(指定后缀名) python拷贝文件 python选择文件对话 ...

  3. ios截屏 u3d导出Xcode工程截屏

    在ios原生程序里面 全屏截屏 UIWindow *window = [[UIApplication sharedApplication] keyWindow]; //下边是经典的4步 UIGraph ...

  4. telegram纯协议电报群发,自动加群,引流自动化解放双手*

    全自动协议批量发送,一键简便操作,极大节省时间和精力.遇到问题时,日志自动诊断,整个过程无需人工干预.目前市场上功能最全面的国内外营销软件,吸引流量效果卓越!

  5. Python解放双手系列——用python自动追踪你的快递!

    前言 最近国内疫情状况好转,快递业也逐渐恢复,大家的快递是不是跑起来了?本文就来讲解如何让 python自动为你查询快递信息 ,并在物流发生更新或者到达指定地点时第一时间将 物流推送至你的邮箱 其实并 ...

  6. Python解放双手系列——用python自动追踪你的快递

    前言 最近国内疫情状况好转,快递业也逐渐恢复,大家的快递是不是跑起来了?本文就来讲解如何让python自动为你查询快递信息,并在物流发生更新或者到达指定地点时第一时间将物流推送至你的邮箱 其实并不复杂 ...

  7. Python解放双手系列,用python自动追踪你的快递

    前言 最近国内疫情状况好转,快递业也逐渐恢复,大家的快递是不是跑起来了?本文就来讲解如何让python自动为你查询快递信息,并在物流发生更新或者到达指定地点时第一时间将物流推送至你的邮箱 其实并不复杂 ...

  8. Android 系统(198)---Android解放双手之Gradle自动化打包实战

    Android解放双手之Gradle自动化打包实战 https://www.jianshu.com/u/0111a7da544b 前言 解放双手,双击桌面快捷方式生成apk包,基于Gradle.bat ...

  9. 模拟手机浏览器_干货系列,让浏览器自己动起来,解放双手

    上一篇干货系列[不记得密码了?教你查看设备保存的账号密码,绝对干货]一经推出,大家反响热烈,纷纷表示要小编多来几篇秀操作的干货. 于是今天就给大家带来怎么让浏览器自己动起来的分享,实现简单的自动化操作 ...

最新文章

  1. 算法设计与分析第3章 贪心算法
  2. JAVA数据结构-稀疏数组
  3. 瞧瞧,这样的『函数』才叫 Pythonic
  4. 任意java程序都可以是servlet吗_C#从Java servlet中获取文件流实现任意文件下载
  5. Report Builder 3.0连接ORACEL数据库
  6. tomcat配置及其中部分目录作用虚拟路径虚拟主机
  7. hbase插入数据语句_记一次 spark thriftserver 插入数据到hbase 的异常
  8. git使用之搭建git仓库
  9. 【李宏毅2020 ML/DL】P24 Semi-supervised
  10. struts中几种常用的Action
  11. SQL数据库中日期时间类型,按日期group by 实现
  12. Atitit maven配置pom文件 配置法v2 t33 目录 1. Maven打包war原理 1 1.1. 在target目录生成war包ori目录。。。里面就是所有的资源 1 1.2. 去掉
  13. JS下载地图离线数据,前端下载谷歌离线地图
  14. mysql的casewhen 作用_MySQL数据库之Mysql casewhen的三种用法
  15. 56个免费资源网站,总有你想要的。
  16. [重要笔记]路由器的包转发操作(全面认识路由器)
  17. 知识图谱问答的测评指标
  18. 绘制自己的人际关系图_人际关系图
  19. 教你如何查看附近的WiFi密码
  20. 网站繁简体切换(一)

热门文章

  1. 小啊呜产品读书笔记001:《邱岳的产品手记-05》第9讲 产品案例分析:Hopper的“人工智能” 第10讲 产品被抄袭了怎么办?
  2. python爬虫代理的使用_从零开始写Python爬虫 --- 2.4 爬虫实践:代理的爬取和验证...
  3. 将宇宙最强vscode打造为刷题神器
  4. 小米首页二级菜单栏实现原理
  5. java wsdl 参数必填设置
  6. 第一次在Vue项目中播放m3u8格式视频遇到的问题和解决方法
  7. python opencv实现 tiff转raw格式以及扩充体积补零
  8. 2021-05-29当微商怎么引流?微商如何利用闲鱼引流?
  9. 小米连续点击Android,屏幕自动点击
  10. (10.1.3.2)浅谈扁平化设计—– keep it simple