Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
什么是混合應(yīng)用
移動端應(yīng)用有兩種典型的開發(fā)方式,一種是原生的 native app,一種是基于網(wǎng)頁開發(fā)技術(shù)的 web app。 原生應(yīng)用的體驗感更好,但是如果想同時開發(fā)安卓應(yīng)用和 ios 應(yīng)用,需要不同的原生開發(fā)技術(shù)。 web 應(yīng)用可以非常輕松的做到安卓和 ios 的跨平臺開發(fā),它的體驗感要稍微差一些,不像原生應(yīng)用那么流暢。
Hybrid App(混合模式移動應(yīng)用)是介于 web app和native app之間的開發(fā)方式,可以在原生界面中嵌套網(wǎng)頁,因而可以同時具備體驗感和跨平臺能力。
目前主流的移動端 app 測試框架 appium 具備混合應(yīng)用測試的能力,但是這個框架搭建和使用都比較麻煩,封裝的方法也沒有那么 pythonic,因此有很多公司不想使用,他們更加喜歡簡潔優(yōu)雅的 python uiautomator2 框架。 非常遺憾,這個框架目前沒有支持混合應(yīng)用測試。
混合應(yīng)用測試步驟
第一步,通過原生操作進(jìn)入 webview 網(wǎng)頁;
第二步,使用 selenium 等網(wǎng)頁測試工具進(jìn)入網(wǎng)頁;
第三步,使用 selenium 等網(wǎng)頁測試工具測試。
這中間的關(guān)鍵步驟在于如何使用 selenium, 如果直接打開一個新的 selenium 會話,那么會打開一個新的頁面,和 app 中的 webview 是分開的,因此無法測到嵌套網(wǎng)頁。 selenium 必須要和 app 建立某種關(guān)系,使他們綁定在一起,操作 selenium 時就是直接操作 app 當(dāng)中的網(wǎng)頁。
通過 uiautomator2 進(jìn)入 webview
這里就是最基本的 uiautomator2 操作,詳細(xì)操作可以查看官方文檔, 這里使用的 app 是 android bootstrap 。
d=u2.connect()
d.app_start('com.github.android_app_bootstrap')
d(text='Login').click()
d(text='Baidu').click()
selenium 連接 webview
APP 的第三個菜單可以直接打開 baidu 網(wǎng)頁,從而到 webview 網(wǎng)頁。 如果不使用 selenium 連接,直接通過 uiautomator2 定位網(wǎng)頁中的元素,是會報錯的。
那如何通過 selenium 連接 webview 呢?
首先,通過設(shè)備 d 獲取當(dāng)前操作的 app, 從而得到包名
然后,初始化一個 Chrome 瀏覽器對象
需要注意的是,Chrome 對象需要添加額外的參數(shù),指定連接的設(shè)備,webview 綁定的報名,以及配置在 app 中使用 android 瀏覽器。
之后的操作就和 selenium 做 web 自動化測試沒有任何區(qū)別了,無非就是點擊網(wǎng)頁,做自動化操作:
driver=webdriver.Chrome('chromedriver_68.exe', options=options)
driver.implicitly_wait(8)
driver.find_element('id', 'index-kw').send_keys('你好')
這段代碼我在哪里學(xué)到的
是不是很好奇,我怎么知道要這么寫代碼,才能連接 webview ,達(dá)到測試效果? 其實世間沒有那么多神秘的學(xué)習(xí)方法,只要你肯用心,一定是可以找到學(xué)習(xí)的路徑的。 這段代碼清清楚楚的寫在 chrome webdriver 的官方文檔中,只是,你可能打不開。 截屏看一下:
其他 webdriver 的配置也可以查看 MDN web docs。
展示效果:
我們都知道對于桌面應(yīng)用開發(fā)來說,人們常用的方式就是采用c++或者c#,java等進(jìn)行開發(fā),然而這些語言開發(fā)效率不夠高,不如網(wǎng)頁開發(fā)靈活。因此,人們思考能否采用html+css+js的方式來開發(fā)桌面客戶端呢,于是人們就提出了混合開發(fā)概念,并且開發(fā)了electron框架進(jìn)行桌面開發(fā)。
提到electron開發(fā)的桌面應(yīng)用,就不得不提vscode,這個采用css+js+html開發(fā)的編輯器從誕生以來就逐漸占據(jù)市場的份額,現(xiàn)在幾乎絕大部分的前端開發(fā)者都采用vscode進(jìn)行開發(fā),而且也有很多后端開發(fā)者逐漸采用vscode進(jìn)行后端開發(fā),可以說vscode證明了electron也可以開發(fā)出優(yōu)秀的桌面程序。當(dāng)然,除了vscode之外,whatsapp和twitch還有slack也是采用electron開發(fā)的。
webview2是微軟推出的一組控件,它可以讓本地應(yīng)用程序輕松嵌入web技術(shù)。WebView2 控件使用Microsoft Edge作為呈現(xiàn)引擎在本機(jī)應(yīng)用程序中顯示 Web 內(nèi)容。使用 WebView2,您可以將 Web 代碼嵌入到本機(jī)應(yīng)用程序的不同部分,或在單個 WebView 實例中構(gòu)建所有本機(jī)應(yīng)用程序。
Webview2 應(yīng)用程序允許廣泛的覆蓋范圍。作為 Web 開發(fā)人員,您可以跨不同平臺重用大部分代碼。對于要訪問本機(jī)平臺的所有功能,則推薦直接使用本機(jī)應(yīng)用程序。
之所以稱為 WebView2,是因為它取代了 WebView 控件,而后者又取代了 WebBrowser 控件,老派 Win32 開發(fā)人員可能還記得。WebView 使用原始的 Edge (Trident) 渲染引擎,是 Windows10 唯一的控件。WebView2 使用較新的 Edge 渲染引擎,并支持多種Windows 平臺。
Electron 為常見的桌面應(yīng)用程序需求提供 API,例如菜單、文件系統(tǒng)訪問、通知等。
WebView2 是一個組件,旨在集成到 WinForms、WPF、WinUI 或 Win32 等應(yīng)用程序框架中。
Node.js 被集成到 Electron 中。Electron 應(yīng)用程序可以使用來自渲染器和主進(jìn)程的 Node.js API、模塊或 node-native-addon。
WebView2 應(yīng)用程序支持嵌入到多種編程語言之中。您的 JavaScript 代碼必須通過應(yīng)用程序主機(jī)進(jìn)程代理執(zhí)行訪問操作系統(tǒng)。
Electron 努力保持與 Web API 的兼容性。
Electron 具有可配置的 Web 內(nèi)容安全模型,從完全訪問到完全沙盒。WebView2 內(nèi)容始終被沙盒化.
目前的webview2還只是支持windows的各個版本預(yù)覽,未來,webview將會支持UWP 預(yù)覽 ,macOS 預(yù)覽,Xbox 預(yù)覽,HoloLens 預(yù)覽,Linux 預(yù)覽,總之,webview2未來可期。
pring Boot中,你可能想要基于動態(tài)內(nèi)容生成靜態(tài)HTML頁面。有幾種方法可以實現(xiàn)這一目標(biāo),以下是其中的一些方法:
下面是一個使用Thymeleaf的簡單示例:
@Service
public class StaticHtmlGeneratorService {
@Autowired
private TemplateEngine templateEngine;
@Autowired
private ApplicationContext applicationContext;
public void generateStaticHtml(String templateName, Map<String, Object> context, String outputPath) {
Context thContext=new Context();
thContext.setVariables(context);
String processedHtml=templateEngine.process(templateName, thContext);
try (BufferedWriter writer=new BufferedWriter(new FileWriter(outputPath))) {
writer.write(processedHtml);
} catch (IOException e) {
// Handle exception
}
}
}
這段代碼不是完整的實現(xiàn),因為TemplateEngine類并不是Spring Boot標(biāo)準(zhǔn)庫中的一部分。在實際應(yīng)用中,你會使用具體的模板引擎的API(例如Thymeleaf的TemplateEngine),并相應(yīng)地調(diào)整代碼。
實際上,Spring Boot集成Thymeleaf后,你會這樣使用Thymeleaf的API:
@Autowired
private SpringTemplateEngine templateEngine;
public void generateStaticHtml(String templateName, Map<String, Object> contextVars, String outputPath) {
Context context=new Context();
context.setVariables(contextVars);
String processedHtml=templateEngine.process(templateName, context);
// Write the processedHtml to a file
// ...
}
public void generateStaticHtmlWithJsoup(String title, String bodyContent, String outputPath) throws IOException {
Document doc=Jsoup.parse("<html><head><title></title></head><body></body></html>");
doc.title(title);
doc.body().append(bodyContent);
// 美化輸出(Pretty-print)
doc.outputSettings().prettyPrint(true);
// 寫入文件
Files.write(Paths.get(outputPath), doc.outerHtml().getBytes(StandardCharsets.UTF_8));
}
@Autowired
private RestTemplate restTemplate;
public void generateStaticHtmlFromWebService(String url, String outputPath) throws IOException {
ResponseEntity<String> response=restTemplate.getForEntity(url, String.class);
if (response.getStatusCode()==HttpStatus.OK) {
Files.write(Paths.get(outputPath), response.getBody().getBytes(StandardCharsets.UTF_8));
}
}
在生成靜態(tài)HTML時,請考慮以下幾點:
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。