JS與APP原生控件交互

  “熱更新”、“熱部署”相信對于混合式開發的童鞋一定不陌生,那么APP怎么避免每次升級都要在APP應用商店發布呢?這里就用到了混合式開發的概念,對于電商網站尤其顯得重要,不可能每次發布一個活動,都要發布一個現版本,當然這樣對于Android還算可以,但是對于Ios呢?蘋果應用商店每次審核的時間基本都在1~2周,這對于一個促銷活動來說審核時間實在太長。而混合式開發正好可以解決這個問題,基本的原理時,通過原生控件實現APP的主體結構,借助H5開發對應的頁面,這樣每次發布活動,只需要在服務器端,將活動發布,便可以達到所有安裝用戶不升級便可查閱最新活動的效果。今天就為大家分享一下,如何實現JavaScript與APP原生控件交互。

  一、首先為大家介紹的是JS與Android交互,首先讓大家看一下Android工程的目錄結構:

  

  JSObject.java文件封裝了JS調用Android原生控件的方法;MainActivity.java是調用WebView控件實現網頁頁面加載,以及進行控件調用JS方法的封裝;test.html是我們加載的HTML頁面。接下來我們具體看一下實現:

  MainActivity.java

package com.chinaonenet.mywebview;import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;/*** SuppressLint一定要加上去!!!* 低版本可能沒問題,高版本JS鐵定調不了Android里面的方法*/
@SuppressLint("SetJavaScriptEnabled")
public class MainActivity extends Activity {private Button button1,button2;private WebView mWebView;private MyWebViewClient WVClient;private WebSettings webSettings;private MyWebChromeClient chromeClient;//封裝接收js調用Android的方法類private JSObject  jsobject;//異步請求private Handler mHandler = new Handler();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();initView();setButton();}private void setButton() {//無參調用button1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mHandler.post(new Runnable() {@Overridepublic void run() {mWebView.loadUrl("javascript:showNoMessage()");}});}});//有參調用button2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mHandler.post(new Runnable() {@Overridepublic void run() {mWebView.loadUrl("javascript:showMessage('順帶給JS傳個參數')");}});}});}private void init() {mWebView = (WebView) findViewById(R.id.webview);button1 = (Button)findViewById(R.id.button1);button2 = (Button)findViewById(R.id.button2);WVClient = new MyWebViewClient();chromeClient = new MyWebChromeClient();jsobject = new JSObject(MainActivity.this); }private void initView() {webSettings = mWebView.getSettings();webSettings.setJavaScriptEnabled(true);webSettings.setBuiltInZoomControls(true);webSettings.setSavePassword(false);//支持多種分辨率,需要js網頁支持webSettings.setUserAgentString("mac os");webSettings.setDefaultTextEncodingName("utf-8");//顯示本地js網頁mWebView.loadUrl("file:///android_asset/test.html");mWebView.setWebViewClient(WVClient);mWebView.setWebChromeClient(chromeClient);//注意第二個參數android,這個是JS網頁調用Android方法的一個類似ID的東西mWebView.addJavascriptInterface(jsobject, "android");}
}

  頁面的配置文件(activity_main.xml)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.chinaonenet.mywebview.MainActivity" ><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:text="無參" /><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:text="有參" /><WebViewandroid:id="@+id/webview"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_alignParentLeft="true"android:layout_alignParentRight="true"android:layout_below="@+id/button2" /><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBaseline="@+id/button1"android:layout_alignBottom="@+id/button1"android:layout_centerHorizontal="true"android:text="js與android交互" /></RelativeLayout>

  JSObject.java

package com.chinaonenet.mywebview;import org.json.JSONArray;
import org.json.JSONException;import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.webkit.JavascriptInterface;
import android.widget.Toast;/*** JS調用android的方法* @JavascriptInterface仍然必不可少*/
public class JSObject {private Context context;public JSObject(Context context){this.context = context;}//js調用無參方法
    @JavascriptInterfacepublic void callNull(){Toast.makeText(context, "JsCallAndroid", Toast.LENGTH_SHORT).show();}//js調用有參方法
    @JavascriptInterfacepublic void callMessage(String data){Toast.makeText(context, data, Toast.LENGTH_SHORT).show();}//js調用有參方法,參數類型:JSON
    @JavascriptInterfacepublic void callJson(String data) throws JSONException{JSONArray jsonArray = new JSONArray(data);Toast.makeText(context, jsonArray.toString(), Toast.LENGTH_SHORT).show();}//js調用有參方法,參數類型:JSON,獲取電話號碼撥打
    @JavascriptInterfacepublic void callPhone(String data){context.startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + data)));}
}

  加載的HTML頁面:

<style>.main-wrap ul {width: 100%;display: inline-block;padding-top: 20px;}.main-wrap ul li {float: left;width: 100%;height: 40px;line-height: 40px;font-size: 14px;margin-bottom: 20px;background-color: #00D000;color: #fff;text-align: center;cursor: pointer;}.main-wrap ul li:active {opacity: 0.8;}
</style><div class="main-wrap"><ul class="postAndroid"><li onclick="jsCallAndroid('1')">不傳參數調用原生控件</li><li onclick="jsCallAndroid('2')">傳參數調用原生控件</li><li onclick="jsCallAndroid('3')">以JSON格式傳參數調用原生控件</li><li onclick="jsCallAndroid('4')">調用打電話服務</li></ul>
</div><script>function jsCallAndroid(rel) {switch(rel){case "1":android.callNull();break;case "2":android.callMessage("javaScript操作Android原生");break;case "3":var json = "[{\"name\":\"滿藝網\", \"phone\":\"4008366069\"}]";android.callJson(json);break;case "4":android.callPhone("4008366069");break;}}function showNoMessage() {alert("Android無參調用");}function showMessage(data) {alert("Android有參調用-data:" + data);}
</script>

  這里因為需要實現一個撥打電話的功能,所以需要在AndroidManifest.xml文件中添加撥打電話的權限:

<uses-permission android:name="android.permission.CALL_PHONE" />

  當然這里加載的頁面是本地頁面,當加載網絡頁面時需要添加請求網絡權限:

<uses-permission android:name="android.permission.INTERNET" />

  好了關于JS與Android原生的控件進行相互調用的知識就介紹完了,最后附上DEML下載地址:http://pan.baidu.com/s/1eR6l7Fk? 提取密碼:4st0

  二、JS與IOS原生交互,這里的開發語言選用的是Swift語言,版本是2.2。首先上工程目錄結構:

  

  ViewController.swift

import UIKit
import JavaScriptCoreclass ViewController: UIViewController {var context = JSContext()var jsContext: JSContext?@IBOutlet weak var webView: UIWebView!override func viewDidLoad() {super.viewDidLoad()webView.delegate = self//初始化webView
        loadJS()}/***加載html頁面*/func loadJS() {let str = NSBundle.mainBundle().pathForResource("test", ofType: "html")let request = NSURLRequest(URL: NSURL(string: str!)!)webView.loadRequest(request)}//Swift 調用JS 方法 (無參數)
    @IBAction func swift_js_pargram(sender: AnyObject) {self.context.evaluateScript("Swift_JS1()")//self.webView.stringByEvaluatingJavaScriptFromString("Swift_JS1()") //此方法也可行
    }//Swift 調用JS 方法 (有參數)
    @IBAction func swift_js_nopargam(sender: AnyObject) {self.context.evaluateScript("Swift_JS2('Ios' ,'Swift')")//self.webView.stringByEvaluatingJavaScriptFromString("Swift_JS2('oc','swift')") //此方法也可行
    }//js調用Swift方法(無參)
    func menthod1() {print("JS調用了無參數swift方法")let title = "操作提示";let msg = "JS調用了無參數swift方法";//創建提示信息let alert = UIAlertController(title: title, message: msg, preferredStyle: .Alert)//確定按鈕alert.addAction(UIAlertAction(title: "ok", style: .Default, handler: nil))//顯示提示框self.presentViewController(alert, animated: true, completion: nil)}//js調用Swift方法(有參數)
    func menthod2(str1: String, str2: String) {print("JS調用了有參數swift方法:參數為\(str1),\(str2)")//創建提示信息let alert = UIAlertController(title: str1, message: str2, preferredStyle: .Alert)//確定按鈕alert.addAction(UIAlertAction(title: "ok", style: .Default, handler: nil))//顯示提示框self.presentViewController(alert, animated: true, completion: nil)}func webView(webView: UIWebView, didFailLoadWithError error: NSError) {print(error)}
}//js調用Swift方法注入
extension ViewController: UIWebViewDelegate {func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {let str = NSBundle.mainBundle().pathForResource("test", ofType: "html")let request = NSURLRequest(URL: NSURL(string: str!)!)let connecntion = NSURLConnection(request: request, delegate: self)connecntion?.start()return true}func webViewDidStartLoad(webView: UIWebView) {print("webViewDidStartLoad----")}func webViewDidFinishLoad(webView: UIWebView) {self.context = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext//JS調用了無參數swift方法---menthod1let temp1: @convention(block) () ->() = {self.menthod1()}//forKeyedSubscript:參數為JS調用方法名self.context.setObject(unsafeBitCast(temp1, AnyObject.self), forKeyedSubscript: "test1")//JS調用了有參數swift方法---menthod2let temp2: @convention(block) () ->() = {let array = JSContext.currentArguments()//這里接到的array中的內容是JSValue類型for object in array {print("參數:" + object.toString())}self.menthod2(array[0].toString(), str2: array[1].toString())}//forKeyedSubscript:參數為JS調用方法名self.context.setObject(unsafeBitCast(temp2, AnyObject.self), forKeyedSubscript: "test2")//模型注入的方法let model = JSObjCModel()model.controller = selfmodel.jsContext = contextself.jsContext = context//這一步是將OCModel這個模型注入到JS中,JS就可以通過OCModel調用我們公暴露的方法了。self.jsContext?.setObject(model, forKeyedSubscript: "OCModel")let url = NSBundle.mainBundle().URLForResource("test", withExtension: "html")self.jsContext?.evaluateScript(try? String(contentsOfURL: url!, encoding: NSUTF8StringEncoding));self.jsContext?.exceptionHandler = {(context, exception) inprint("exception @", exception)}}
}@objc protocol JavaScriptSwiftDelegate: JSExport {func callSystemCamera()func showAlert(title: String, msg: String)func callWithDict(dict: [String: AnyObject])func jsCallObjcAndObjcCallJsWithDict(dict: [String: AnyObject])
}//js調用Swift模型方法
@objc class JSObjCModel: NSObject, JavaScriptSwiftDelegate {weak var controller: UIViewController?weak var jsContext: JSContext?//JS無參調用Swift方法并返回處理結果
    func callSystemCamera() {print("js call objc method: callSystemCamera");let jsFunc = self.jsContext?.objectForKeyedSubscript("jsFunc");jsFunc?.callWithArguments([]);}//JS有參調用Swift方法
    func showAlert(title: String, msg: String) {print("js call objc method: showAlert, title: %@", title, "   msg: %@", msg)dispatch_async(dispatch_get_main_queue()) { () -> Void inlet alert = UIAlertController(title: title, message: msg, preferredStyle: .Alert)alert.addAction(UIAlertAction(title: "ok", style: .Default, handler: nil))self.controller?.presentViewController(alert, animated: true, completion: nil)}}//JS有參調用Swift方法
    func callWithDict(dict: [String : AnyObject]) {print("js call objc method: callWithDict, args: %@", dict)let alert = UIAlertController(title: "消息提示", message: "查看控制臺打印信息", preferredStyle: .Alert)alert.addAction(UIAlertAction(title: "ok", style: .Default, handler: nil))self.controller?.presentViewController(alert, animated: true, completion: nil)}//JS有參調用Swift方法并返回處理結果
    func jsCallObjcAndObjcCallJsWithDict(dict: [String : AnyObject]) {print("js call objc method: jsCallObjcAndObjcCallJsWithDict, args: %@", dict)let jsParamFunc = self.jsContext?.objectForKeyedSubscript("jsParamFunc");let dict = NSDictionary(dictionary: ["age": 2, "height": 178, "name": "滿藝網"])jsParamFunc?.callWithArguments([dict])}
}extension ViewController: NSURLConnectionDelegate,NSURLConnectionDataDelegate {func connection(connection: NSURLConnection, didReceiveData data: NSData) {print("didReceiveData\(data)")}func connection(connection: NSURLConnection, willSendRequest request: NSURLRequest, redirectResponse response: NSURLResponse?) -> NSURLRequest? {print("request:\(request)response:\(response)")return request}func connection(connection: NSURLConnection, didFailWithError error: NSError) {}
}//MARK: - allowsAnyHTTPSCertificateForHost
extension NSURLRequest {static func allowsAnyHTTPSCertificateForHost(host: String) -> Bool {return true}
}

  test.html

<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>JSAndIos</title></head><style>.main-wrap ul {width: 100%;display: inline-block;padding-top: 20px;}.main-wrap ul li {float: left;width: 100%;height: 40px;line-height: 40px;font-size: 14px;margin-bottom: 20px;background-color: #00D000;color: #fff;text-align: center;cursor: pointer;}.main-wrap ul li:active {opacity: 0.8;}</style><body bgcolor="#dddd"><div class="main-wrap"><ul class="postAndroid"><li onclick="JS_Swift1()">不傳參數調用原生控件(常規方式)</li><li onclick="JS_Swift2()">傳參數調用原生控件(常規方式)</li><li onclick="JS_Swift3()">不傳參數調用原生控件,帶返回結果處理(模型注入)</li><li onclick="JS_Swift4()">傳參數調用原生控件(模型注入)</li><li onclick="JS_Swift5()">傳對象格式參數調用原生控件(模型注入)</li><li onclick="JS_Swift6()">傳對象格式參數調用原生控件,帶返回結果處理(模型注入)</li></ul></div><script>function Swift_JS1() {alert("Swift調用Js無參方法");}function Swift_JS2(name,msg) {alert("Swift調用Js有參方法,name:"+name+";mes:"+msg);}function JS_Swift1() {test1();}function JS_Swift2() {test2('JsCallSwift', 'Js調用Swift方法');}function JS_Swift3() {OCModel.callSystemCamera();}//js調用Swift方法,處理返回結果function jsFunc() {alert('JS調用Swift方法,無返回值結果處理');}function JS_Swift4() {OCModel.showAlertMsg('js send title', 'js send message');}function JS_Swift5() {OCModel.callWithDict({ 'name': 'testname', 'age': 10, 'height': 170 });}function JS_Swift6() {OCModel.jsCallObjcAndObjcCallJsWithDict({ 'name': 'testname', 'age': 10, 'height': 170 });}//注意哦,如果JS寫錯,可能在OC調用JS方法時,都會出錯哦。function jsParamFunc (argument) {alert("JS調用Swift方法,有返回值處理結果---name:"+argument['name'] + "    age:" + argument['age']);}</script></body>
</html>

  好了,對于JS與Ios原生控件之間進行相互調用的主要內容就分享完畢了,DEML下載地址:鏈接: https://pan.baidu.com/s/1bpEFzaR 密碼: y5ms

  到這里關于JS與Android、IOS原生控件相互之間進行調用的知識就為大家分享完畢,歡迎留言討論,相互學習。

轉載于:https://www.cnblogs.com/AndroidJotting/p/6237407.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/456610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/456610.shtml
英文地址,請注明出處:http://en.pswp.cn/news/456610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《脫穎而出——成功網店經營之道》一2.6 連橫:返利模式的應用及分銷

本節書摘來異步社區《脫穎而出——成功網店經營之道》一書中的第2章&#xff0c;第2.6節&#xff0c;作者&#xff1a; 何小健 責編&#xff1a; 趙軒, 更多章節內容可以訪問云棲社區“異步社區”公眾號查看。 2.6 連橫&#xff1a;返利模式的應用及分銷 脫穎而出——成功網店…

【python】os模塊 遞歸刪除文件夾所有文件 --筆記

os.environ 獲取系統的環境變量 os.name nt -- windows \r\n | posix --- Linux \nos.path: import osprint(os.environ) print(os.environ[OS])print(os.path.abspath(t1/file01.py)) # 獲取絕對路徑 print(os.path.isabs(t1/file01.py)) # 判斷所給的路徑是否是一個絕對…

大數據之Spark集群安裝及簡單使用

目錄1、Spark集群安裝1.1. 安裝 2、啟動Spark Shell2.1、啟動spark shell2.2、在spark shell中編寫WordCount程序 目錄 1、Spark集群安裝 1.1. 安裝 1.1.1. 機器部署 準備兩臺以上Linux服務器&#xff0c;安裝好JDK1.7 1.1.2. 下載Spark安裝包 下載地址&#xff1a;ht…

《C和C++代碼精粹》——1.7 類型安全I/O

本節書摘來自異步社區出版社《C和C代碼精粹》一書中的第1章第1.7節&#xff0c;作者&#xff1a; 【美】Chuck Allison&#xff0c;更多章節內容可以訪問云棲社區“異步社區”公眾號查看。 1.7 類型安全I/O C和C代碼精粹當然每個C程序員都曾經使用過printf的錯誤格式描述符號。…

大數據之Spark簡介及RDD說明

目錄前言&#xff1a;1、Spark概述1.1、什么是Spark&#xff08;官網&#xff1a;http://spark.apache.org&#xff09;1.2、為什么要學Spark1.3、Spark特點 2、RDD概述2.1、什么是RDD2.2、RDD的屬性2.3、創建RDD的兩種方式2.4、RDD編程API2.5、RDD的依賴關系2.6、RDD的緩存2.7…

Python3中urlopen()詳解

一. 簡介 urllib.request.urlopen()函數用于實現對目標url的訪問。 函數原型如下&#xff1a;urllib.request.urlopen(url, dataNone, [timeout, ]*, cafileNone, capathNone, cadefaultFalse, contextNone)  url: 需要打開的網址 data&#xff1a;Post提交的數據 timeo…

python面向對象實現簡易銀行管理員頁面系統

銀行管理員頁面系統設計:card 類&#xff1a; cardId password moneyuser 類: username phone id cards[]銀行的工作人員: 賬號 密碼 登錄 展現管理系統所有功能Bank類:開戶取錢存錢轉賬銷戶查賬解鎖... import pickle import random# 銀行卡 import time#card 類…

單子模式

package test; class aceing { /** param args */ private static aceing ace; public aceing() { super(); System.out.println("aceing類中的無參構造器調用了"); } public static aceing getAceing() { if(ace null) { ace new aceing(); } return ace; }} pack…

《塑造互聯網思維的企業》一一第4章 全球商務向社會化媒體的轉變

第4章 全球商務向社會化媒體的轉變 塑造互聯網思維的企業社會化媒體在發達國家的廣泛采用已是我們所熟知的&#xff0c;它在社會和全球文化產生的大范圍變革中至關重要。為了完全了解其中的原因&#xff0c;有必要探究一下那些推動社會化商務的復雜且相互關聯的因素的共同影響…

大數據之SparkSQL簡介及DataFrame的使用

目錄前言&#xff1a;1、Spark SQL1.1、Spark SQL概述1.2、DataFrames1.3、DataFrame常用操作 總結&#xff1a; 目錄 前言&#xff1a; 本文主要介紹下SparkSQL以及SparkSQL的簡單使用。這里只是做了一個非常簡單的介紹&#xff0c;后續工作中如果有用到相關的知識&#xff…

python的各種推導式(列表推導式、字典推導式、集合推導式)

python的各種推導式&#xff08;列表推導式、字典推導式、集合推導式&#xff09; 推導式comprehensions&#xff08;又稱解析式&#xff09;&#xff0c;是Python的一種獨有特性。推導式是可以從一個數據序列構建另一個新的數據序列的結構體。 共有三種推導&#xff0c;在Pyt…

原生js實現jquery庫中選擇器的功能(jquery庫封裝一)

今天是2017.1.1&#xff0c;新的一天&#xff0c;新的一年&#xff0c;新的一年里繼續夯實基礎知識&#xff0c;在工作中多些項目&#xff0c;多思考&#xff0c;多總結&#xff0c;前端是不斷更新&#xff0c;在更新的過程中也是發現樂趣和挑戰自我的過程&#xff0c;希望年輕…

Ubantu下使用vi時,方向鍵變字母輸出、退格鍵無法刪除字符的解決辦法

目錄前言&#xff1a;一、編輯/etc/vim/vimrc.tiny二、安裝vim full版本三、添加”.vimrc”文件 目錄 前言&#xff1a; 最近由于要玩TensorFlow&#xff0c;所以把塵封已久的Ubantu給打開了&#xff0c;不過配置網絡的時候&#xff0c;算是一團糟&#xff0c;出現了在插入模…

《Python爬蟲開發與項目實戰》——第3章 初識網絡爬蟲 3.1 網絡爬蟲概述

本節書摘來自華章計算機《Python爬蟲開發與項目實戰》一書中的第3章&#xff0c;第3.1節&#xff0c;作者&#xff1a;范傳輝著&#xff0c;更多章節內容可以訪問云棲社區“華章計算機”公眾號查看 第3章 初識網絡爬蟲 從本章開始&#xff0c;將正式涉及Python爬蟲的開發。本章…

【python】解決:TypeError: can't send non-None value to a just-started generator

在一個生成器函數未啟動之前&#xff0c;是不能傳遞數值進去。必須先傳遞一個None進去或者調用一次next(g)方法&#xff0c;才能進行傳值操作 def product(c):# c.send(None)for i in range(5):print("生產者產生數據%d"%i)r c.send(str(i))print("消費者消費了…

Shell腳本與vi編輯器:vi啟動與退出、工作模式、命令大全

Vi簡介 Vi是一種廣泛存在于各種UNIX和Linux系統中的文本編輯程序。Vi不是排版程序&#xff0c;只是一個純粹的文本編輯程序。Vi是全屏幕文本編輯器&#xff0c;它沒有菜單&#xff0c;只有命令。Vi不是基于窗口的&#xff0c;所以&#xff0c;這個多用途編輯程序可以用于在任何…

windows環境下,如何在Pycharm下安裝TensorFlow環境

文章目錄目錄前言&#xff1a;1.安裝Anaconda2.安裝Tensorflow3.其他問題4.在pycharm中使用tensorflow目錄 前言&#xff1a; 最近由于工作需要要使用TensorFlow&#xff0c;所以只能狂補相關的知識。本來博主打算在Ubantu上玩&#xff0c;但是由于一些原因還是放棄了這個想法…

python面向對象實現簡易銀行管理員頁面系統【導入自定義模塊】

main.py 人 類名&#xff1a;Person 屬性&#xff1a;姓名 身份證號 電話 卡 行為&#xff1a;卡 類名&#xff1a;Card 屬性&#xff1a;卡號 密碼 余額 行為&#xff1a;銀行 類名&#xff1a;Bank 屬性&#xff1a;用戶列表 提款機提款機 類名&#xff1a;ATM 屬性&#xf…

[轉] dpkg-deb命令

點擊此處閱讀原文 軟件包管理 dpkg-deb命令是Debian Linux下的軟件包管理工具&#xff0c;它可以對軟件包執行打包和解包操作以及提供軟件包信息。 語法dpkg-deb(選項)(參數) 選項-c&#xff1a;顯示軟件包中的文件列表&#xff1b; -e&#xff1a;將主控信息解壓&#xff1b;…

《Effective Debugging:軟件和系統調試的66個有效方法》一第5條:在能夠正常運作的系統與發生故障的系統之間尋找差別...

本節書摘來自華章出版社《Effective Debugging&#xff1a;軟件和系統調試的66個有效方法》一書中的第1章&#xff0c;第1.5節&#xff0c;作&#xff3b;希&#xff3d;迪歐米迪斯斯賓奈里斯&#xff08;Diomidis Spinellis&#xff09;&#xff0c;更多章節內容可以訪問云棲社…