Android四大组件之ContentProvider-程序员宅基地

技术标签: Android  

1.ContentProvider定义

这里通过一个实际的例子来说明ContentProvider(内容提供者)是什么,作用是什么

短信应用要访问通讯录应用中的数据,是不能直接访问的,应用通讯录的中的数据是属于通讯录app数据库中的数据,无法直接访问

通讯录应用使用ContentProvider将数据库表数据操作(增删改查)暴露给其他应用(包括本身)访问

其他应用通过ContentResolver来调用ContentProvider方法

ContentResolver和ContentProvider之间是通过URI交流

作用

进程间 进行数据交互 & 共享,即跨进程通信

2.Url

统一资源标识符,唯一标识 ContentProvider & 其中的数据,外界进程通过 URI 找到对应的ContentProvider & 其中的数据,再进行数据操作

以联系人Contacts的Uri为例,其结构如下所示:

 

  • schema: Android中固定为content://。
  • authority: 用于唯一标识一个ContentProvider。
  • path: ContentProvider中数据表的表名。
  • id: 数据表中数据的标识,可选字段。

注意:

// 设置URI
Uri uri = Uri.parse("content://com.demo.provider/User/1")
// 上述URI指向的资源是:名为 `com.demo.provider`的`ContentProvider` 中表名 为`User` 中的 `id`为1的数据

// 特别注意:URI模式存在匹配通配符* & #

// *:匹配任意长度的任何有效字符的字符串
// 以下的URI 表示 匹配provider的任何内容
content://com.example.app.provider/*
// #:匹配任意长度的数字字符的字符串
// 以下的URI 表示 匹配provider中的table表的所有行
content://com.example.app.provider/table/#

3.MIME数据类型

3.1概述

指定某个扩展名的文件用某种应用程序来打开,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
如指定.html文件采用text应用程序打开、指定.pdf文件采用flash应用程序打开

格式前面为后缀名,后面为对应的MIME型

(例如: ".apk", "application/vnd.android.package-archive" 表示。.apk对应的是application/vnd.android.package-archive)

3.2具体使用

ContentProvider根据 URI 返回MIME类型

ContentProvider.geType(uri) ;

3.3MIME类型组成

每种MIME类型 由2部分组成 = 类型 + 子类型

MIME类型是 一个 包含2部分的字符串

text / html
// 类型 = text、子类型 = html

text/css
text/xml
application/pdf

 3.4MIME类型形式

MIME类型有2种形式:

 
// 形式1:单条记录  
vnd.android.demo.item/自定义
// 形式2:多条记录(集合)
vnd.android.demo.dir/自定义 

// 注:
  // 1. vnd:表示父类型和子类型具有非标准的、特定的形式。
  // 2. 父类型已固定好(即不能更改),只能区别是单条还是多条记录
  // 3. 子类型可自定义

 实例

<-- 单条记录 -->
  // 单个记录的MIME类型
  vnd.android.cursor.item/vnd.yourcompanyname.contenttype 

  // 若一个Uri如下
  content://com.example.transportationprovider/trains/122   
  // 则ContentProvider会通过ContentProvider.geType(url)返回以下MIME类型
  vnd.android.cursor.item/vnd.example.rail


<-- 多条记录 -->
  // 多个记录的MIME类型
  vnd.android.cursor.dir/vnd.yourcompanyname.contenttype 
  // 若一个Uri如下
  content://com.example.transportationprovider/trains 
  // 则ContentProvider会通过ContentProvider.geType(url)返回以下MIME类型
  vnd.android.cursor.dir/vnd.example.rail

3.5MIME类型大全

import java.io.File;
 
public class MimeTest {
	/**
	 * MIME全部类型映射
	 */
	final static String[][] MIME_MapTable = {
			{ ".323", "text/h323" },
			{ ".3gp", "video/3gpp" },
			{ ".aab", "application/x-authoware-bin" },
			{ ".aam", "application/x-authoware-map" },
			{ ".aas", "application/x-authoware-seg" },
			{ ".acx", "application/internet-property-stream" },
			{ ".ai", "application/postscript" },
			{ ".aif", "audio/x-aiff" },
			{ ".aifc", "audio/x-aiff" },
			{ ".aiff", "audio/x-aiff" },
			{ ".als", "audio/X-Alpha5" },
			{ ".amc", "application/x-mpeg" },
			{ ".ani", "application/octet-stream" },
			{ ".apk", "application/vnd.android.package-archive" },
			{ ".asc", "text/plain" },
			{ ".asd", "application/astound" },
			{ ".asf", "video/x-ms-asf" },
			{ ".asn", "application/astound" },
			{ ".asp", "application/x-asap" },
			{ ".asr", "video/x-ms-asf" },
			{ ".asx", "video/x-ms-asf" },
			{ ".au", "audio/basic" },
			{ ".avb", "application/octet-stream" },
			{ ".avi", "video/x-msvideo" },
			{ ".awb", "audio/amr-wb" },
			{ ".axs", "application/olescript" },
			{ ".bas", "text/plain" },
			{ ".bcpio", "application/x-bcpio" },
			{ ".bin ", "application/octet-stream" },
			{ ".bld", "application/bld" },
			{ ".bld2", "application/bld2" },
			{ ".bmp", "image/bmp" },
			{ ".bpk", "application/octet-stream" },
			{ ".bz2", "application/x-bzip2" },
			{ ".c", "text/plain" },
			{ ".cal", "image/x-cals" },
			{ ".cat", "application/vnd.ms-pkiseccat" },
			{ ".ccn", "application/x-cnc" },
			{ ".cco", "application/x-cocoa" },
			{ ".cdf", "application/x-cdf" },
			{ ".cer", "application/x-x509-ca-cert" },
			{ ".cgi", "magnus-internal/cgi" },
			{ ".chat", "application/x-chat" },
			{ ".class", "application/octet-stream" },
			{ ".clp", "application/x-msclip" },
			{ ".cmx", "image/x-cmx" },
			{ ".co", "application/x-cult3d-object" },
			{ ".cod", "image/cis-cod" },
			{ ".conf", "text/plain" },
			{ ".cpio", "application/x-cpio" },
			{ ".cpp", "text/plain" },
			{ ".cpt", "application/mac-compactpro" },
			{ ".crd", "application/x-mscardfile" },
			{ ".crl", "application/pkix-crl" },
			{ ".crt", "application/x-x509-ca-cert" },
			{ ".csh", "application/x-csh" },
			{ ".csm", "chemical/x-csml" },
			{ ".csml", "chemical/x-csml" },
			{ ".css", "text/css" },
			{ ".cur", "application/octet-stream" },
			{ ".dcm", "x-lml/x-evm" },
			{ ".dcr", "application/x-director" },
			{ ".dcx", "image/x-dcx" },
			{ ".der", "application/x-x509-ca-cert" },
			{ ".dhtml", "text/html" },
			{ ".dir", "application/x-director" },
			{ ".dll", "application/x-msdownload" },
			{ ".dmg", "application/octet-stream" },
			{ ".dms", "application/octet-stream" },
			{ ".doc", "application/msword" },
			{ ".docx",
					"application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
			{ ".dot", "application/msword" },
			{ ".dvi", "application/x-dvi" },
			{ ".dwf", "drawing/x-dwf" },
			{ ".dwg", "application/x-autocad" },
			{ ".dxf", "application/x-autocad" },
			{ ".dxr", "application/x-director" },
			{ ".ebk", "application/x-expandedbook" },
			{ ".emb", "chemical/x-embl-dl-nucleotide" },
			{ ".embl", "chemical/x-embl-dl-nucleotide" },
			{ ".eps", "application/postscript" },
			{ ".epub", "application/epub+zip" },
			{ ".eri", "image/x-eri" },
			{ ".es", "audio/echospeech" },
			{ ".esl", "audio/echospeech" },
			{ ".etc", "application/x-earthtime" },
			{ ".etx", "text/x-setext" },
			{ ".evm", "x-lml/x-evm" },
			{ ".evy", "application/envoy" },
			{ ".exe", "application/octet-stream" },
			{ ".fh4", "image/x-freehand" },
			{ ".fh5", "image/x-freehand" },
			{ ".fhc", "image/x-freehand" },
			{ ".fif", "application/fractals" },
			{ ".flr", "x-world/x-vrml" },
			{ ".flv", "flv-application/octet-stream" },
			{ ".fm", "application/x-maker" },
			{ ".fpx", "image/x-fpx" },
			{ ".fvi", "video/isivideo" },
			{ ".gau", "chemical/x-gaussian-input" },
			{ ".gca", "application/x-gca-compressed" },
			{ ".gdb", "x-lml/x-gdb" },
			{ ".gif", "image/gif" },
			{ ".gps", "application/x-gps" },
			{ ".gtar", "application/x-gtar" },
			{ ".gz", "application/x-gzip" },
			{ ".h", "text/plain" },
			{ ".hdf", "application/x-hdf" },
			{ ".hdm", "text/x-hdml" },
			{ ".hdml", "text/x-hdml" },
			{ ".hlp", "application/winhlp" },
			{ ".hqx", "application/mac-binhex40" },
			{ ".hta", "application/hta" },
			{ ".htc", "text/x-component" },
			{ ".htm", "text/html" },
			{ ".html", "text/html" },
			{ ".hts", "text/html" },
			{ ".htt", "text/webviewhtml" },
			{ ".ice", "x-conference/x-cooltalk" },
			{ ".ico", "image/x-icon" },
			{ ".ief", "image/ief" },
			{ ".ifm", "image/gif" },
			{ ".ifs", "image/ifs" },
			{ ".iii", "application/x-iphone" },
			{ ".imy", "audio/melody" },
			{ ".ins", "application/x-internet-signup" },
			{ ".ips", "application/x-ipscript" },
			{ ".ipx", "application/x-ipix" },
			{ ".isp", "application/x-internet-signup" },
			{ ".it", "audio/x-mod" },
			{ ".itz", "audio/x-mod" },
			{ ".ivr", "i-world/i-vrml" },
			{ ".j2k", "image/j2k" },
			{ ".jad", "text/vnd.sun.j2me.app-descriptor" },
			{ ".jam", "application/x-jam" },
			{ ".jar", "application/java-archive" },
			{ ".java", "text/plain" },
			{ ".jfif", "image/pipeg" },
			{ ".jnlp", "application/x-java-jnlp-file" },
			{ ".jpe", "image/jpeg" },
			{ ".jpeg", "image/jpeg" },
			{ ".jpg", "image/jpeg" },
			{ ".jpz", "image/jpeg" },
			{ ".js", "application/x-javascript" },
			{ ".jwc", "application/jwc" },
			{ ".kjx", "application/x-kjx" },
			{ ".lak", "x-lml/x-lak" },
			{ ".latex", "application/x-latex" },
			{ ".lcc", "application/fastman" },
			{ ".lcl", "application/x-digitalloca" },
			{ ".lcr", "application/x-digitalloca" },
			{ ".lgh", "application/lgh" },
			{ ".lha", "application/octet-stream" },
			{ ".lml", "x-lml/x-lml" },
			{ ".lmlpack", "x-lml/x-lmlpack" },
			{ ".log", "text/plain" },
			{ ".lsf", "video/x-la-asf" },
			{ ".lsx", "video/x-la-asf" },
			{ ".lzh", "application/octet-stream" },
			{ ".m13", "application/x-msmediaview" },
			{ ".m14", "application/x-msmediaview" },
			{ ".m15", "audio/x-mod" },
			{ ".m3u", "audio/x-mpegurl" },
			{ ".m3url", "audio/x-mpegurl" },
			{ ".m4a", "audio/mp4a-latm" },
			{ ".m4b", "audio/mp4a-latm" },
			{ ".m4p", "audio/mp4a-latm" },
			{ ".m4u", "video/vnd.mpegurl" },
			{ ".m4v", "video/x-m4v" },
			{ ".ma1", "audio/ma1" },
			{ ".ma2", "audio/ma2" },
			{ ".ma3", "audio/ma3" },
			{ ".ma5", "audio/ma5" },
			{ ".man", "application/x-troff-man" },
			{ ".map", "magnus-internal/imagemap" },
			{ ".mbd", "application/mbedlet" },
			{ ".mct", "application/x-mascot" },
			{ ".mdb", "application/x-msaccess" },
			{ ".mdz", "audio/x-mod" },
			{ ".me", "application/x-troff-me" },
			{ ".mel", "text/x-vmel" },
			{ ".mht", "message/rfc822" },
			{ ".mhtml", "message/rfc822" },
			{ ".mi", "application/x-mif" },
			{ ".mid", "audio/mid" },
			{ ".midi", "audio/midi" },
			{ ".mif", "application/x-mif" },
			{ ".mil", "image/x-cals" },
			{ ".mio", "audio/x-mio" },
			{ ".mmf", "application/x-skt-lbs" },
			{ ".mng", "video/x-mng" },
			{ ".mny", "application/x-msmoney" },
			{ ".moc", "application/x-mocha" },
			{ ".mocha", "application/x-mocha" },
			{ ".mod", "audio/x-mod" },
			{ ".mof", "application/x-yumekara" },
			{ ".mol", "chemical/x-mdl-molfile" },
			{ ".mop", "chemical/x-mopac-input" },
			{ ".mov", "video/quicktime" },
			{ ".movie", "video/x-sgi-movie" },
			{ ".mp2", "video/mpeg" },
			{ ".mp3", "audio/mpeg" },
			{ ".mp4", "video/mp4" },
			{ ".mpa", "video/mpeg" },
			{ ".mpc", "application/vnd.mpohun.certificate" },
			{ ".mpe", "video/mpeg" },
			{ ".mpeg", "video/mpeg" },
			{ ".mpg", "video/mpeg" },
			{ ".mpg4", "video/mp4" },
			{ ".mpga", "audio/mpeg" },
			{ ".mpn", "application/vnd.mophun.application" },
			{ ".mpp", "application/vnd.ms-project" },
			{ ".mps", "application/x-mapserver" },
			{ ".mpv2", "video/mpeg" },
			{ ".mrl", "text/x-mrml" },
			{ ".mrm", "application/x-mrm" },
			{ ".ms", "application/x-troff-ms" },
			{ ".msg", "application/vnd.ms-outlook" },
			{ ".mts", "application/metastream" },
			{ ".mtx", "application/metastream" },
			{ ".mtz", "application/metastream" },
			{ ".mvb", "application/x-msmediaview" },
			{ ".mzv", "application/metastream" },
			{ ".nar", "application/zip" },
			{ ".nbmp", "image/nbmp" },
			{ ".nc", "application/x-netcdf" },
			{ ".ndb", "x-lml/x-ndb" },
			{ ".ndwn", "application/ndwn" },
			{ ".nif", "application/x-nif" },
			{ ".nmz", "application/x-scream" },
			{ ".nokia-op-logo", "image/vnd.nok-oplogo-color" },
			{ ".npx", "application/x-netfpx" },
			{ ".nsnd", "audio/nsnd" },
			{ ".nva", "application/x-neva1" },
			{ ".nws", "message/rfc822" },
			{ ".oda", "application/oda" },
			{ ".ogg", "audio/ogg" },
			{ ".oom", "application/x-AtlasMate-Plugin" },
			{ ".p10", "application/pkcs10" },
			{ ".p12", "application/x-pkcs12" },
			{ ".p7b", "application/x-pkcs7-certificates" },
			{ ".p7c", "application/x-pkcs7-mime" },
			{ ".p7m", "application/x-pkcs7-mime" },
			{ ".p7r", "application/x-pkcs7-certreqresp" },
			{ ".p7s", "application/x-pkcs7-signature" },
			{ ".pac", "audio/x-pac" },
			{ ".pae", "audio/x-epac" },
			{ ".pan", "application/x-pan" },
			{ ".pbm", "image/x-portable-bitmap" },
			{ ".pcx", "image/x-pcx" },
			{ ".pda", "image/x-pda" },
			{ ".pdb", "chemical/x-pdb" },
			{ ".pdf", "application/pdf" },
			{ ".pfr", "application/font-tdpfr" },
			{ ".pfx", "application/x-pkcs12" },
			{ ".pgm", "image/x-portable-graymap" },
			{ ".pict", "image/x-pict" },
			{ ".pko", "application/ynd.ms-pkipko" },
			{ ".pm", "application/x-perl" },
			{ ".pma", "application/x-perfmon" },
			{ ".pmc", "application/x-perfmon" },
			{ ".pmd", "application/x-pmd" },
			{ ".pml", "application/x-perfmon" },
			{ ".pmr", "application/x-perfmon" },
			{ ".pmw", "application/x-perfmon" },
			{ ".png", "image/png" },
			{ ".pnm", "image/x-portable-anymap" },
			{ ".pnz", "image/png" },
			{ ".pot,", "application/vnd.ms-powerpoint" },
			{ ".ppm", "image/x-portable-pixmap" },
			{ ".pps", "application/vnd.ms-powerpoint" },
			{ ".ppt", "application/vnd.ms-powerpoint" },
			{ ".pptx",
					"application/vnd.openxmlformats-officedocument.presentationml.presentation" },
			{ ".pqf", "application/x-cprplayer" },
			{ ".pqi", "application/cprplayer" },
			{ ".prc", "application/x-prc" },
			{ ".prf", "application/pics-rules" },
			{ ".prop", "text/plain" },
			{ ".proxy", "application/x-ns-proxy-autoconfig" },
			{ ".ps", "application/postscript" },
			{ ".ptlk", "application/listenup" },
			{ ".pub", "application/x-mspublisher" },
			{ ".pvx", "video/x-pv-pvx" },
			{ ".qcp", "audio/vnd.qcelp" },
			{ ".qt", "video/quicktime" },
			{ ".qti", "image/x-quicktime" },
			{ ".qtif", "image/x-quicktime" },
			{ ".r3t", "text/vnd.rn-realtext3d" },
			{ ".ra", "audio/x-pn-realaudio" },
			{ ".ram", "audio/x-pn-realaudio" },
			{ ".rar", "application/octet-stream" },
			{ ".ras", "image/x-cmu-raster" },
			{ ".rc", "text/plain" },
			{ ".rdf", "application/rdf+xml" },
			{ ".rf", "image/vnd.rn-realflash" },
			{ ".rgb", "image/x-rgb" },
			{ ".rlf", "application/x-richlink" },
			{ ".rm", "audio/x-pn-realaudio" },
			{ ".rmf", "audio/x-rmf" },
			{ ".rmi", "audio/mid" },
			{ ".rmm", "audio/x-pn-realaudio" },
			{ ".rmvb", "audio/x-pn-realaudio" },
			{ ".rnx", "application/vnd.rn-realplayer" },
			{ ".roff", "application/x-troff" },
			{ ".rp", "image/vnd.rn-realpix" },
			{ ".rpm", "audio/x-pn-realaudio-plugin" },
			{ ".rt", "text/vnd.rn-realtext" },
			{ ".rte", "x-lml/x-gps" },
			{ ".rtf", "application/rtf" },
			{ ".rtg", "application/metastream" },
			{ ".rtx", "text/richtext" },
			{ ".rv", "video/vnd.rn-realvideo" },
			{ ".rwc", "application/x-rogerwilco" },
			{ ".s3m", "audio/x-mod" },
			{ ".s3z", "audio/x-mod" },
			{ ".sca", "application/x-supercard" },
			{ ".scd", "application/x-msschedule" },
			{ ".sct", "text/scriptlet" },
			{ ".sdf", "application/e-score" },
			{ ".sea", "application/x-stuffit" },
			{ ".setpay", "application/set-payment-initiation" },
			{ ".setreg", "application/set-registration-initiation" },
			{ ".sgm", "text/x-sgml" },
			{ ".sgml", "text/x-sgml" },
			{ ".sh", "application/x-sh" },
			{ ".shar", "application/x-shar" },
			{ ".shtml", "magnus-internal/parsed-html" },
			{ ".shw", "application/presentations" },
			{ ".si6", "image/si6" },
			{ ".si7", "image/vnd.stiwap.sis" },
			{ ".si9", "image/vnd.lgtwap.sis" },
			{ ".sis", "application/vnd.symbian.install" },
			{ ".sit", "application/x-stuffit" },
			{ ".skd", "application/x-Koan" },
			{ ".skm", "application/x-Koan" },
			{ ".skp", "application/x-Koan" },
			{ ".skt", "application/x-Koan" },
			{ ".slc", "application/x-salsa" },
			{ ".smd", "audio/x-smd" },
			{ ".smi", "application/smil" },
			{ ".smil", "application/smil" },
			{ ".smp", "application/studiom" },
			{ ".smz", "audio/x-smd" },
			{ ".snd", "audio/basic" },
			{ ".spc", "application/x-pkcs7-certificates" },
			{ ".spl", "application/futuresplash" },
			{ ".spr", "application/x-sprite" },
			{ ".sprite", "application/x-sprite" },
			{ ".sdp", "application/sdp" },
			{ ".spt", "application/x-spt" },
			{ ".src", "application/x-wais-source" },
			{ ".sst", "application/vnd.ms-pkicertstore" },
			{ ".stk", "application/hyperstudio" },
			{ ".stl", "application/vnd.ms-pkistl" },
			{ ".stm", "text/html" },
			{ ".svg", "image/svg+xml" },
			{ ".sv4cpio", "application/x-sv4cpio" },
			{ ".sv4crc", "application/x-sv4crc" },
			{ ".svf", "image/vnd" },
			{ ".svg", "image/svg+xml" },
			{ ".svh", "image/svh" },
			{ ".svr", "x-world/x-svr" },
			{ ".swf", "application/x-shockwave-flash" },
			{ ".swfl", "application/x-shockwave-flash" },
			{ ".t", "application/x-troff" },
			{ ".tad", "application/octet-stream" },
			{ ".talk", "text/x-speech" },
			{ ".tar", "application/x-tar" },
			{ ".taz", "application/x-tar" },
			{ ".tbp", "application/x-timbuktu" },
			{ ".tbt", "application/x-timbuktu" },
			{ ".tcl", "application/x-tcl" },
			{ ".tex", "application/x-tex" },
			{ ".texi", "application/x-texinfo" },
			{ ".texinfo", "application/x-texinfo" },
			{ ".tgz", "application/x-compressed" },
			{ ".thm", "application/vnd.eri.thm" },
			{ ".tif", "image/tiff" },
			{ ".tiff", "image/tiff" },
			{ ".tki", "application/x-tkined" },
			{ ".tkined", "application/x-tkined" },
			{ ".toc", "application/toc" },
			{ ".toy", "image/toy" },
			{ ".tr", "application/x-troff" },
			{ ".trk", "x-lml/x-gps" },
			{ ".trm", "application/x-msterminal" },
			{ ".tsi", "audio/tsplayer" },
			{ ".tsp", "application/dsptype" },
			{ ".tsv", "text/tab-separated-values" },
			{ ".ttf", "application/octet-stream" },
			{ ".ttz", "application/t-time" },
			{ ".txt", "text/plain" },
			{ ".uls", "text/iuls" },
			{ ".ult", "audio/x-mod" },
			{ ".ustar", "application/x-ustar" },
			{ ".uu", "application/x-uuencode" },
			{ ".uue", "application/x-uuencode" },
			{ ".vcd", "application/x-cdlink" },
			{ ".vcf", "text/x-vcard" },
			{ ".vdo", "video/vdo" },
			{ ".vib", "audio/vib" },
			{ ".viv", "video/vivo" },
			{ ".vivo", "video/vivo" },
			{ ".vmd", "application/vocaltec-media-desc" },
			{ ".vmf", "application/vocaltec-media-file" },
			{ ".vmi", "application/x-dreamcast-vms-info" },
			{ ".vms", "application/x-dreamcast-vms" },
			{ ".vox", "audio/voxware" },
			{ ".vqe", "audio/x-twinvq-plugin" },
			{ ".vqf", "audio/x-twinvq" },
			{ ".vql", "audio/x-twinvq" },
			{ ".vre", "x-world/x-vream" },
			{ ".vrml", "x-world/x-vrml" },
			{ ".vrt", "x-world/x-vrt" },
			{ ".vrw", "x-world/x-vream" },
			{ ".vts", "workbook/formulaone" },
			{ ".wav", "audio/x-wav" },
			{ ".wax", "audio/x-ms-wax" },
			{ ".wbmp", "image/vnd.wap.wbmp" },
			{ ".wcm", "application/vnd.ms-works" },
			{ ".wdb", "application/vnd.ms-works" },
			{ ".web", "application/vnd.xara" },
			{ ".wi", "image/wavelet" },
			{ ".wis", "application/x-InstallShield" },
			{ ".wks", "application/vnd.ms-works" },
			{ ".wm", "video/x-ms-wm" },
			{ ".wma", "audio/x-ms-wma" },
			{ ".wmd", "application/x-ms-wmd" },
			{ ".wmf", "application/x-msmetafile" },
			{ ".wml", "text/vnd.wap.wml" },
			{ ".wmlc", "application/vnd.wap.wmlc" },
			{ ".wmls", "text/vnd.wap.wmlscript" },
			{ ".wmlsc", "application/vnd.wap.wmlscriptc" },
			{ ".wmlscript", "text/vnd.wap.wmlscript" },
			{ ".wmv", "audio/x-ms-wmv" },
			{ ".wmx", "video/x-ms-wmx" },
			{ ".wmz", "application/x-ms-wmz" },
			{ ".wpng", "image/x-up-wpng" },
			{ ".wps", "application/vnd.ms-works" },
			{ ".wpt", "x-lml/x-gps" },
			{ ".wri", "application/x-mswrite" },
			{ ".wrl", "x-world/x-vrml" },
			{ ".wrz", "x-world/x-vrml" },
			{ ".ws", "text/vnd.wap.wmlscript" },
			{ ".wsc", "application/vnd.wap.wmlscriptc" },
			{ ".wv", "video/wavelet" },
			{ ".wvx", "video/x-ms-wvx" },
			{ ".wxl", "application/x-wxl" },
			{ ".x-gzip", "application/x-gzip" },
			{ ".xaf", "x-world/x-vrml" },
			{ ".xar", "application/vnd.xara" },
			{ ".xbm", "image/x-xbitmap" },
			{ ".xdm", "application/x-xdma" },
			{ ".xdma", "application/x-xdma" },
			{ ".xdw", "application/vnd.fujixerox.docuworks" },
			{ ".xht", "application/xhtml+xml" },
			{ ".xhtm", "application/xhtml+xml" },
			{ ".xhtml", "application/xhtml+xml" },
			{ ".xla", "application/vnd.ms-excel" },
			{ ".xlc", "application/vnd.ms-excel" },
			{ ".xll", "application/x-excel" },
			{ ".xlm", "application/vnd.ms-excel" },
			{ ".xls", "application/vnd.ms-excel" },
			{ ".xlsx",
					"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" },
			{ ".xlt", "application/vnd.ms-excel" },
			{ ".xlw", "application/vnd.ms-excel" }, { ".xm", "audio/x-mod" },
			{ ".xml", "text/plain" }, { ".xml", "application/xml" },
			{ ".xmz", "audio/x-mod" }, { ".xof", "x-world/x-vrml" },
			{ ".xpi", "application/x-xpinstall" },
			{ ".xpm", "image/x-xpixmap" }, { ".xsit", "text/xml" },
			{ ".xsl", "text/xml" }, { ".xul", "text/xul" },
			{ ".xwd", "image/x-xwindowdump" }, { ".xyz", "chemical/x-pdb" },
			{ ".yz1", "application/x-yz1" },
			{ ".z", "application/x-compress" },
			{ ".zac", "application/x-zaurus-zac" },
			{ ".zip", "application/zip" }, { ".json", "application/json" } };
 
	/**
	 * 根据文件后缀名获得对应的MIME类型。
	 * @param file
	 */
	public static String getMIMEType(File file) {
		String type = "*/*";
		String fName = file.getName();
		// 获取后缀名前的分隔符"."在fName中的位置。
		int dotIndex = fName.lastIndexOf(".");
		if (dotIndex < 0) {
			return type;
		}
		/* 获取文件的后缀名 */
		String end = fName.substring(dotIndex, fName.length()).toLowerCase();
		if (end == "")
			return type;
		// 在MIME和文件类型的匹配表中找到对应的MIME类型。
		for (int i = 0; i < MIME_MapTable.length; i++) { 
			if (end.equals(MIME_MapTable[i][0]))
				type = MIME_MapTable[i][1];
		}
		return type;
	}
	public static void main(String[] args) {
		//下面输出为:application/vnd.android.package-archive
		System.out.println(MimeTest.getMIMEType(new File("C:\\oyp.apk")));
	}
}

4.ContentProvider类

4.1概述

ContentProvider主要以 表格的形式 组织数据,同时也支持文件数据,只是表格形式用得比较多

每个表格中包含多张表,每张表包含行 & 列,分别对应记录 & 字段

4.2主要方法

进程间共享数据的本质是:添加、删除、获取 & 修改(更新)数据,所以ContentProvider的核心方法也主要是上述4个作用

<-- 4个核心方法 -->
  public Uri insert(Uri uri, ContentValues values) 
  // 外部进程向 ContentProvider 中添加数据

  public int delete(Uri uri, String selection, String[] selectionArgs) 
  // 外部进程 删除 ContentProvider 中的数据

  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
  // 外部进程更新 ContentProvider 中的数据

  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  String sortOrder)  
  // 外部应用 获取 ContentProvider 中的数据

// 注:
  // 1. 上述4个方法由外部进程回调,并运行在ContentProvider进程的Binder线程池中(不是主线程)
 // 2. 存在多线程并发访问,需要实现线程同步
   // a. 若ContentProvider的数据存储方式是使用SQLite & 一个,则不需要,因为SQLite内部实现好了线程同步,若是多个SQLite则需要,因为SQL对象之间无法进行线程同步
  // b. 若ContentProvider的数据存储方式是内存,则需要自己实现线程同步

<-- 2个其他方法 -->
public boolean onCreate() 
// ContentProvider创建后 或 打开系统后其它进程第一次访问该ContentProvider时 由系统进行调用
// 注:运行在ContentProvider进程的主线程,故不能做耗时操作

public String getType(Uri uri)
// 得到数据类型,即返回当前 Url 所代表数据的MIME类型
  • Android为常见的数据(如通讯录、日程表等)提供了内置了默认的ContentProvider,本文主要讲解自定义ContentProvider
  • 但也可根据需求自定义ContentProvider,但上述6个方法必须重写
  • ContentProvider类并不会直接与外部进程交互,而是通过ContentResolver

5.ContentResolver类

5.1概述

统一管理不同 ContentProvider间的操作,即通过 URI 即可操作 不同的ContentProvider 中的数据

外部进程通过 ContentResolver类 从而与ContentProvider类进行交互

为什么要使用通过ContentResolver类从而与ContentProvider类进行交互,而不直接访问ContentProvider类?

答:一般来说,一款应用要使用多个ContentProvider,若需要了解每个ContentProvider的不同实现从而再完成数据交互,操作成本高 & 难度大,所以再ContentProvider类上加多了一个 ContentResolver类对所有的ContentProvider进行统一管理。

5.2方法

// 外部进程向 ContentProvider 中添加数据
public Uri insert(Uri uri, ContentValues values)  

// 外部进程 删除 ContentProvider 中的数据
public int delete(Uri uri, String selection, String[] selectionArgs)

// 外部进程更新 ContentProvider 中的数据
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)  

// 外部应用 获取 ContentProvider 中的数据
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

实例

// 使用ContentResolver前,需要先获取ContentResolver
// 可通过在所有继承Context的类中 通过调用getContentResolver()来获得ContentResolver
ContentResolver resolver =  getContentResolver(); 

// 设置ContentProvider的URI
Uri uri = Uri.parse("content://cn.scu.myprovider/user"); 
 
// 根据URI 操作 ContentProvider中的数据
// 此处是获取ContentProvider中 user表的所有记录 
Cursor cursor = resolver.query(uri, null, null, null, "userid desc"); 

Android 提供了3个用于辅助ContentProvide的工具类:

  • ContentUris 操作 URI

// withAppendedId()作用:向URI追加一个id
Uri uri = Uri.parse("content://cn.scu.myprovider/user") 
Uri resultUri = ContentUris.withAppendedId(uri, 7);  
// 最终生成后的Uri为:content://cn.scu.myprovider/user/7

// parseId()作用:从URL中获取ID
Uri uri = Uri.parse("content://cn.scu.myprovider/user/7") 
long personid = ContentUris.parseId(uri); 
//获取的结果为:7
  • UriMatcher

  1. ContentProvider 中注册URI
  2. 根据 URI 匹配 ContentProvider 中对应的数据表
// 步骤1:初始化UriMatcher对象
    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 
    //常量UriMatcher.NO_MATCH  = 不匹配任何路径的返回码
    // 即初始化时不匹配任何东西

// 步骤2:在ContentProvider 中注册URI(addURI())
    int URI_CODE_a = 1;
    int URI_CODE_b = 2;
    matcher.addURI("cn.scu.myprovider", "user1", URI_CODE_a); 
    matcher.addURI("cn.scu.myprovider", "user2", URI_CODE_b); 
    // 若URI资源路径 = content://cn.scu.myprovider/user1 ,则返回注册码URI_CODE_a
    // 若URI资源路径 = content://cn.scu.myprovider/user2 ,则返回注册码URI_CODE_b

// 步骤3:根据URI 匹配 URI_CODE,从而匹配ContentProvider中相应的资源(match())

@Override   
    public String getType(Uri uri) {   
      Uri uri = Uri.parse(" content://cn.scu.myprovider/user1");   

      switch(matcher.match(uri)){   
     // 根据URI匹配的返回码是URI_CODE_a
     // 即matcher.match(uri) == URI_CODE_a
      case URI_CODE_a:   
        return tableNameUser1;   
        // 如果根据URI匹配的返回码是URI_CODE_a,则返回ContentProvider中的名为tableNameUser1的表
      case URI_CODE_b:   
        return tableNameUser2;
        // 如果根据URI匹配的返回码是URI_CODE_b,则返回ContentProvider中的名为tableNameUser2的表
    }   
}
  • ContentObserver

 内容观察者,观察 Uri引起 ContentProvider 中的数据变化 & 通知外界(即访问该数据访问者),当ContentProvider 中的数据发生变化(增、删 & 改)时,就会触发该 ContentObserver

// 步骤1:注册内容观察者ContentObserver
    getContentResolver().registerContentObserver(uri);
    // 通过ContentResolver类进行注册,并指定需要观察的URI

// 步骤2:当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
    public class UserContentProvider extends ContentProvider { 
      public Uri insert(Uri uri, ContentValues values) { 
      db.insert("user", "userid", values); 
      getContext().getContentResolver().notifyChange(uri, null); 
      // 通知访问者
   } 
}

// 步骤3:解除观察者
 getContentResolver().unregisterContentObserver(uri);
    // 同样需要通过ContentResolver类进行解除

6.实例

6.1实例说明

  • 由于ContentProvider不仅常用于进程间通信,同时也适用于进程内通信
  • 所以本实例会采用ContentProvider讲解:
    1. 进程内通信
    2. 进程间通信
  • 采用的数据源是Android中的SQLite数据库

6.2进程内通信

步骤1:创建数据库类

public class DBHelper extends SQLiteOpenHelper {

    // 数据库名
    private static final String DATABASE_NAME = "finch.db";

    // 表名
    public static final String USER_TABLE_NAME = "user";
    public static final String JOB_TABLE_NAME = "job";

    private static final int DATABASE_VERSION = 1;
    //数据库版本号

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        // 创建两个表格:用户表 和职业表
        db.execSQL("CREATE TABLE IF NOT EXISTS " + USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT," + " name TEXT)");
        db.execSQL("CREATE TABLE IF NOT EXISTS " + JOB_TABLE_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT," + " job TEXT)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)   {

    }
}

步骤2:自定义 ContentProvider

public class MyProvider extends ContentProvider {

    private Context mContext;
    DBHelper mDbHelper = null;
    SQLiteDatabase db = null;

    public static final String AUTOHORITY = "cn.scu.myprovider";
    // 设置ContentProvider的唯一标识

    public static final int User_Code = 1;
    public static final int Job_Code = 2;

    // UriMatcher类使用:在ContentProvider 中注册URI
    private static final UriMatcher mMatcher;
    static{
        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        // 初始化
        mMatcher.addURI(AUTOHORITY,"user", User_Code);
        mMatcher.addURI(AUTOHORITY, "job", Job_Code);
        // 若URI资源路径 = content://cn.scu.myprovider/user ,则返回注册码User_Code
        // 若URI资源路径 = content://cn.scu.myprovider/job ,则返回注册码Job_Code
    }

    // 以下是ContentProvider的6个方法

    /**
     * 初始化ContentProvider
     */
    @Override
    public boolean onCreate() {

        mContext = getContext();
        // 在ContentProvider创建时对数据库进行初始化
        // 运行在主线程,故不能做耗时操作,此处仅作展示
        mDbHelper = new DBHelper(getContext());
        db = mDbHelper.getWritableDatabase();

        // 初始化两个表的数据(先清空两个表,再各加入一个记录)
        db.execSQL("delete from user");
        db.execSQL("insert into user values(1,'Carson');");
        db.execSQL("insert into user values(2,'Kobe');");

        db.execSQL("delete from job");
        db.execSQL("insert into job values(1,'Android');");
        db.execSQL("insert into job values(2,'iOS');");

        return true;
    }

    /**
     * 添加数据
     */

    @Override
    public Uri insert(Uri uri, ContentValues values) {

        // 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
        // 该方法在最下面
        String table = getTableName(uri);

        // 向该表添加数据
        db.insert(table, null, values);

        // 当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
        mContext.getContentResolver().notifyChange(uri, null);

//        // 通过ContentUris类从URL中获取ID
//        long personid = ContentUris.parseId(uri);
//        System.out.println(personid);

        return uri;
        }

    /**
     * 查询数据
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
        // 该方法在最下面
        String table = getTableName(uri);

//        // 通过ContentUris类从URL中获取ID
//        long personid = ContentUris.parseId(uri);
//        System.out.println(personid);

        // 查询数据
        return db.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
    }

    /**
     * 更新数据
     */
    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // 由于不展示,此处不作展开
        return 0;
    }

    /**
     * 删除数据
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // 由于不展示,此处不作展开
        return 0;
    }

    @Override
    public String getType(Uri uri) {

        // 由于不展示,此处不作展开
        return null;
    }

    /**
     * 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
     */
    private String getTableName(Uri uri){
        String tableName = null;
        switch (mMatcher.match(uri)) {
            case User_Code:
                tableName = DBHelper.USER_TABLE_NAME;
                break;
            case Job_Code:
                tableName = DBHelper.JOB_TABLE_NAME;
                break;
        }
        return tableName;
        }
    }

步骤3:注册 创建的 ContentProvider

AndroidManifest.xml

<provider android:name="MyProvider"
                android:authorities="cn.scu.myprovider"
                    />

步骤4:进程内访问 ContentProvider的数据

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /**
         * 对user表进行操作
         */

        // 设置URI
        Uri uri_user = Uri.parse("content://cn.scu.myprovider/user");

        // 插入表中数据
        ContentValues values = new ContentValues();
        values.put("_id", 3);
        values.put("name", "Iverson");


        // 获取ContentResolver
        ContentResolver resolver =  getContentResolver();
        // 通过ContentResolver 根据URI 向ContentProvider中插入数据
        resolver.insert(uri_user,values);

        // 通过ContentResolver 向ContentProvider中查询数据
        Cursor cursor = resolver.query(uri_user, new String[]{"_id","name"}, null, null, null);
        while (cursor.moveToNext()){
            System.out.println("query book:" + cursor.getInt(0) +" "+ cursor.getString(1));
            // 将表中数据全部输出
        }
        cursor.close();
        // 关闭游标

        /**
         * 对job表进行操作
         */
        // 和上述类似,只是URI需要更改,从而匹配不同的URI CODE,从而找到不同的数据资源
        Uri uri_job = Uri.parse("content://cn.scu.myprovider/job");
        
        // 插入表中数据
        ContentValues values2 = new ContentValues();
        values2.put("_id", 3);
        values2.put("job", "NBA Player");

        // 获取ContentResolver
        ContentResolver resolver2 =  getContentResolver();
        // 通过ContentResolver 根据URI 向ContentProvider中插入数据
        resolver2.insert(uri_job,values2);

        // 通过ContentResolver 向ContentProvider中查询数据
        Cursor cursor2 = resolver2.query(uri_job, new String[]{"_id","job"}, null, null, null);
        while (cursor2.moveToNext()){
            System.out.println("query job:" + cursor2.getInt(0) +" "+ cursor2.getString(1));
            // 将表中数据全部输出
        }
        cursor2.close();
        // 关闭游标
}
}

 

6.3进程间通信

本文需要创建2个进程,即创建两个工程,作用如下

进程1:创建ContentProvider+储存数据sqlite

进程2:访问ContentProvider中的储存数据

进程1

步骤1:创建数据库类

步骤2:自定义 ContentProvider

前2个步骤同上例相同

步骤3:注册 创建的 ContentProvider类
AndroidManifest.xml

<provider 
               android:name="MyProvider"
               android:authorities="scut.carson_ho.myprovider"

               // 声明外界进程可访问该Provider的权限(读 & 写)
               android:permission="scut.carson_ho.PROVIDER"             
               
               // 权限可细分为读 & 写的权限
               // 外界需要声明同样的读 & 写的权限才可进行相应操作,否则会报错
               // android:readPermisson = "scut.carson_ho.Read"
               // android:writePermisson = "scut.carson_ho.Write"

               // 设置此provider是否可以被其他进程使用
               android:exported="true"
                
  />

// 声明本应用 可允许通信的权限
    <permission android:name="scut.carson_ho.Read" android:protectionLevel="normal"/>
    // 细分读 & 写权限如下,但本Demo直接采用全权限
    // <permission android:name="scut.carson_ho.Write" android:protectionLevel="normal"/>
    // <permission android:name="scut.carson_ho.PROVIDER" android:protectionLevel="normal"/>

进程2

步骤1:声明可访问的权限

AndroidManifest.xml

    // 声明本应用可允许通信的权限(全权限)
    <uses-permission android:name="scut.carson_ho.PROVIDER"/>

    // 细分读 & 写权限如下,但本Demo直接采用全权限
    // <uses-permission android:name="scut.carson_ho.Read"/>
    //  <uses-permission android:name="scut.carson_ho.Write"/>
    
// 注:声明的权限必须与进程1中设置的权限对应

步骤2:访问 ContentProvider的类

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /**
         * 对user表进行操作
         */

        // 设置URI
        Uri uri_user = Uri.parse("content://scut.carson_ho.myprovider/user");

        // 插入表中数据
        ContentValues values = new ContentValues();
        values.put("_id", 4);
        values.put("name", "Jordan");


        // 获取ContentResolver
        ContentResolver resolver =  getContentResolver();
        // 通过ContentResolver 根据URI 向ContentProvider中插入数据
        resolver.insert(uri_user,values);

        // 通过ContentResolver 向ContentProvider中查询数据
        Cursor cursor = resolver.query(uri_user, new String[]{"_id","name"}, null, null, null);
        while (cursor.moveToNext()){
            System.out.println("query book:" + cursor.getInt(0) +" "+ cursor.getString(1));
            // 将表中数据全部输出
        }
        cursor.close();
        // 关闭游标

        /**
         * 对job表进行操作
         */
        // 和上述类似,只是URI需要更改,从而匹配不同的URI CODE,从而找到不同的数据资源
        Uri uri_job = Uri.parse("content://scut.carson_ho.myprovider/job");

        // 插入表中数据
        ContentValues values2 = new ContentValues();
        values2.put("_id", 4);
        values2.put("job", "NBA Player");

        // 获取ContentResolver
        ContentResolver resolver2 =  getContentResolver();
        // 通过ContentResolver 根据URI 向ContentProvider中插入数据
        resolver2.insert(uri_job,values2);

        // 通过ContentResolver 向ContentProvider中查询数据
        Cursor cursor2 = resolver2.query(uri_job, new String[]{"_id","job"}, null, null, null);
        while (cursor2.moveToNext()){
            System.out.println("query job:" + cursor2.getInt(0) +" "+ cursor2.getString(1));
            // 将表中数据全部输出
        }
        cursor2.close();
        // 关闭游标
    }
}

在进程展示时,需要先运行准备数据的进程1,再运行需要访问数据的进程2

  1. 在进程1中,我们准备好了一系列数据

  2. 在进程2中,我们先向ContentProvider中插入数据,再查询数据

注意:

SQLite数据库使用详见

https://www.jianshu.com/p/8e3f294e2828

参考链接

https://www.jianshu.com/p/ea8bc4aaf057

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_34491508/article/details/103973010

智能推荐

JWT(Json Web Token)实现无状态登录_无状态token登录-程序员宅基地

文章浏览阅读685次。1.1.什么是有状态?有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。缺点是什么?服务端保存大量数据,增加服务端压力 服务端保存用户状态,无法进行水平扩展 客户端请求依赖服务.._无状态token登录

SDUT OJ逆置正整数-程序员宅基地

文章浏览阅读293次。SDUT OnlineJudge#include<iostream>using namespace std;int main(){int a,b,c,d;cin>>a;b=a%10;c=a/10%10;d=a/100%10;int key[3];key[0]=b;key[1]=c;key[2]=d;for(int i = 0;i<3;i++){ if(key[i]!=0) { cout<<key[i.

年终奖盲区_年终奖盲区表-程序员宅基地

文章浏览阅读2.2k次。年终奖采用的平均每月的收入来评定缴税级数的,速算扣除数也按照月份计算出来,但是最终减去的也是一个月的速算扣除数。为什么这么做呢,这样的收的税更多啊,年终也是一个月的收入,凭什么减去12*速算扣除数了?这个霸道(不要脸)的说法,我们只能合理避免的这些跨级的区域了,那具体是那些区域呢?可以参考下面的表格:年终奖一列标红的一对便是盲区的上下线,发放年终奖的数额一定一定要避免这个区域,不然公司多花了钱..._年终奖盲区表

matlab 提取struct结构体中某个字段所有变量的值_matlab读取struct类型数据中的值-程序员宅基地

文章浏览阅读7.5k次,点赞5次,收藏19次。matlab结构体struct字段变量值提取_matlab读取struct类型数据中的值

Android fragment的用法_android reader fragment-程序员宅基地

文章浏览阅读4.8k次。1,什么情况下使用fragment通常用来作为一个activity的用户界面的一部分例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输_android reader fragment

FFT of waveIn audio signals-程序员宅基地

文章浏览阅读2.8k次。FFT of waveIn audio signalsBy Aqiruse An article on using the Fast Fourier Transform on audio signals. IntroductionThe Fast Fourier Transform (FFT) allows users to view the spectrum content of _fft of wavein audio signals

随便推点

Awesome Mac:收集的非常全面好用的Mac应用程序、软件以及工具_awesomemac-程序员宅基地

文章浏览阅读5.9k次。https://jaywcjlove.github.io/awesome-mac/ 这个仓库主要是收集非常好用的Mac应用程序、软件以及工具,主要面向开发者和设计师。有这个想法是因为我最近发了一篇较为火爆的涨粉儿微信公众号文章《工具武装的前端开发工程师》,于是建了这么一个仓库,持续更新作为补充,搜集更多好用的软件工具。请Star、Pull Request或者使劲搓它 issu_awesomemac

java前端技术---jquery基础详解_简介java中jquery技术-程序员宅基地

文章浏览阅读616次。一.jquery简介 jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互 jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax_简介java中jquery技术

Ant Design Table换滚动条的样式_ant design ::-webkit-scrollbar-corner-程序员宅基地

文章浏览阅读1.6w次,点赞5次,收藏19次。我修改的是表格的固定列滚动而产生的滚动条引用Table的组件的css文件中加入下面的样式:.ant-table-body{ &amp;amp;::-webkit-scrollbar { height: 5px; } &amp;amp;::-webkit-scrollbar-thumb { border-radius: 5px; -webkit-box..._ant design ::-webkit-scrollbar-corner

javaWeb毕设分享 健身俱乐部会员管理系统【源码+论文】-程序员宅基地

文章浏览阅读269次。基于JSP的健身俱乐部会员管理系统项目分享:见文末!

论文开题报告怎么写?_开题报告研究难点-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏15次。同学们,是不是又到了一年一度写开题报告的时候呀?是不是还在为不知道论文的开题报告怎么写而苦恼?Take it easy!我带着倾尽我所有开题报告写作经验总结出来的最强保姆级开题报告解说来啦,一定让你脱胎换骨,顺利拿下开题报告这个高塔,你确定还不赶快点赞收藏学起来吗?_开题报告研究难点

原生JS 与 VUE获取父级、子级、兄弟节点的方法 及一些DOM对象的获取_获取子节点的路径 vue-程序员宅基地

文章浏览阅读6k次,点赞4次,收藏17次。原生先获取对象var a = document.getElementById("dom");vue先添加ref <div class="" ref="divBox">获取对象let a = this.$refs.divBox获取父、子、兄弟节点方法var b = a.childNodes; 获取a的全部子节点 var c = a.parentNode; 获取a的父节点var d = a.nextSbiling; 获取a的下一个兄弟节点 var e = a.previ_获取子节点的路径 vue