拓展:
創(chuàng)新互聯(lián)公司一直秉承“誠信做人,踏實做事”的原則,不欺瞞客戶,是我們最起碼的底線! 以服務(wù)為基礎(chǔ),以質(zhì)量求生存,以技術(shù)求發(fā)展,成交一個客戶多一個朋友!為您提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計、成都網(wǎng)頁設(shè)計、微信平臺小程序開發(fā)、成都網(wǎng)站開發(fā)、成都網(wǎng)站制作、成都軟件開發(fā)、手機APP定制開發(fā)是成都本地專業(yè)的網(wǎng)站建設(shè)和網(wǎng)站設(shè)計公司,等你一起來見證!
??Android之Service與IntentService的比較
???? ??http://blog.csdn.net/smile3670/article/details/7702521
保證服務(wù)不被殺死:
http://blog.csdn.net/mad1989/article/details/22492519? ? (提高優(yōu)先級,服務(wù)死掉的時候發(fā)送廣播,重啟服務(wù))
? ??
1.什么是服務(wù)
?就把服務(wù)理解為在后臺長期運行但是沒有界面的Activity,因為Service與Activity有很多相似的地方。
? ?1)啟動一個activity或service都要通過Intent
? ?2) 如果想打開一個activity/service,按是否返回數(shù)據(jù),需要采用不同的方法。
??■服務(wù)的作用
????讓某些邏輯在后臺(長期)執(zhí)行。
????服務(wù)可以結(jié)合廣播接收者碰撞出各種效果(看你的想像力了?。?/p>
2.進程
Foreground process 前臺進程 ?相當于Activity執(zhí)行了onResume方法 用戶正在操作頁面 前臺進程的優(yōu)先級最高
Visible process 可視進程 相當于Activity執(zhí)行了onPasue方法 ?用戶依然能看的見屏幕
Service process 服務(wù)進程 相當于通過startservice方式開啟了一個服務(wù) 在當前進程里面運行
Background process 后臺進程 ?相當于Activity執(zhí)行了onStop方法 ?用戶看不見頁面 但是注意Activity沒有執(zhí)行ondestroy方法?
Empty process 空進程 后臺沒有任何組件運行 這個時候?qū)儆诳者M程?
3.服務(wù)的創(chuàng)建和開啟
? ■服務(wù)的創(chuàng)建:
????定義一個類繼承Service,在清單文件里注冊這個類,<service>標簽。
? ? ?
? ■服務(wù)的開啟:
? ? ?服務(wù)的開啟屬于Context里的方法,所以繼承了Context的類Activity、Service或者是擁有Context對象的類
? ?都可以開啟一個服務(wù)(如廣播接收者的onReceive方法里有Context對象,所以廣播接收者也可以開啟一個服務(wù))
? ?開啟服務(wù)的方式有2種:startService和bindService。
? ? ?不同的方式開啟的服務(wù),作用不同,服務(wù)的生命周期不同,服務(wù)需要復寫的方法也不同,掌握
? ?這兩種開啟服務(wù)的方式區(qū)別十分地重要。(********重點*********)
????如果想要服務(wù)長期運行,就用startService方法;如果想調(diào)用服務(wù)里的方法,就用bindService
? ?方法來開啟服務(wù)。
????不同方式開啟服務(wù)的生命周期圖:
? ? ??
? ? ?1)startService方式開啟服務(wù)
????????★當用戶第一次調(diào)用start-service方法 服務(wù)會執(zhí)行onCreate、onStartCommand、onStart方法?
????????★當用戶第二次調(diào)用start-service方法 服務(wù)只會走onStartCommand、onStart方法?
????????★服務(wù)一旦通過start-service方法開啟后 服務(wù)就會在后臺長期運行 直到用戶手工停止或調(diào)用
? ? ?????? stopService方法停止,或者服務(wù)調(diào)用自身的stopSelf()方法。如下圖,手動關(guān)閉service:
????????
???????★start開啟服務(wù)代碼
????????????//啟動服務(wù) ????????????????Intent?intent?=?new?Intent(this,CallService.class); ????????????????startService(intent);
? ??
? ? ?
? ? ?2)bindService方式開啟服務(wù)? ?
????★第一次點擊按鈕?通過bindservice開啟服務(wù)?服務(wù)只會走?onCreate?和?onbind方法
????★第二次點擊按鈕?通過bindservice開啟服務(wù)??服務(wù)沒有反應(yīng)?
????★不求同時生?但求同時死??只的是Activity和服務(wù)之間,Activity一掛掉,bind方式開啟的服務(wù)也會
???? ?隨之掛掉
????★服務(wù)只能解綁一次?多次解綁會報異常?
????★通過bindservice方式開啟服務(wù)?在設(shè)置頁面找不到?他可以理解成是一個隱形的服務(wù)??
????★當服務(wù)的onbind方法返回null的時候onServiceConnected方法不執(zhí)行?
??????
????▇bindservice方式調(diào)用服務(wù)方法里面的流程(**********重點**********)
????????(1)定義一個服務(wù) 在清單文件里面配置 ?在服務(wù)里面定義一個方法 ?
????????(2)Activity想調(diào)用服務(wù)里面的方法?
????????(3)在服務(wù)的內(nèi)部定義一個中間人對象(IBinder) 在這個實現(xiàn)類里面可以間接的調(diào)用到服務(wù)里面的
????????? ?方法
????????(4)在onbind方法中把我們自己定義的這個中間人對象返回?
????????(5)當Activity想調(diào)用服務(wù)里面方法的時候 ?先通過bindservice方法獲取中間人對象?
????????(6)通過我們獲取的中間人對象就可以間接調(diào)用到服務(wù)里面的方法了?
????????
? ? ? ? ?一般寫在"中間人"對象(IBinder)里的方法,都是實現(xiàn)接口里的方法,再在方法里調(diào)用服
? ? ? ?務(wù)里定義的方法。
?????■綁定服務(wù)抽取接口
????????接口可以隱藏代碼內(nèi)部的細節(jié) 讓程序員暴露只想暴露的方法
????????實現(xiàn)步驟
????????(1)定義一個接口 把服務(wù)里面想暴露方法都定義在接口里 ?
????????(2)我們定義的這個中間人對象實現(xiàn)我們定義的這個接口?
????????(3)還是通過bindservice方式獲取我們中間人的對象
????????(4)還是通過中間人對象間接調(diào)用服務(wù)里面的方法
?
4.應(yīng)用1_電話竊聽器案例(startService開啟服務(wù)方式)
? ? 需求:手機一接聽電話就把通話進行錄音,保存起來。
? ? 實現(xiàn)思路:電話竊聽,肯定不希望用戶看到,所以不需要界面,那么竊聽錄音的邏輯應(yīng)寫在服務(wù)里。服務(wù)有了,
? ? ? ? ? 需要被開啟,為了顯得應(yīng)用更智能一些,就定義一個廣播接收者來接收開機廣播來開啟服務(wù)了。
? ? 具體實現(xiàn)步驟:
? ? 1)定義電話竊聽錄音邏輯的服務(wù)類
????創(chuàng)建服務(wù)類之后,按照好的編程習慣,立馬在清單里配置service標簽。?
public?class?CallService?extends?Service?{ private?MediaRecorder?recorder?=?null; @Override public?IBinder?onBind(Intent?arg0)?{ return?null; } @Override public?void?onCreate()?{ super.onCreate(); //創(chuàng)建一個TelephonyManager對象 //注意要強轉(zhuǎn) TelephonyManager?manager?=?(TelephonyManager)?this.getSystemService(this.TELEPHONY_SERVICE); //通過TelephonyManager來獲取通話的狀態(tài)?????????????????????/ manager.listen(new?MyPoneListener(),?PhoneStateListener.LISTEN_CALL_STATE); //注意常量是PhoneStateListener的常量。 } //定義一個類繼承PhoneListener private?class?MyPoneListener?extends?PhoneStateListener{ //復寫它的一個監(jiān)聽通話狀態(tài)的方法 @Override public?void?onCallStateChanged(int?state,?String?incomingNumber)?{ //判斷狀態(tài) /*int? CALL_STATE_IDLE? Device?call?state:?No?activity. int? CALL_STATE_OFFHOOK? Device?call?state:?Off-hook. int? CALL_STATE_RINGING? Device?call?state:?Ringing.*/ //代表空閑狀態(tài) if(state?==?TelephonyManager.CALL_STATE_IDLE) { System.out.println("結(jié)束錄音"); if(recorder?!=?null) { ?recorder.stop(); ?recorder.reset();???//?You?can?reuse?the?object?by?going?back?to?setAudioSource()?step ?recorder.release();?//?Now?the?object?cannot?be?reused } } //接聽狀態(tài) else?if(state?==?TelephonyManager.CALL_STATE_OFFHOOK) { System.out.println("開始錄音"); if(recorder?!=?null) { recorder.start();???//?Recording?is?now?started } } //響鈴狀態(tài) if(state?==?TelephonyManager.CALL_STATE_RINGING) { System.out.println("準備錄音,創(chuàng)建錄音機。"); recorder?=?new?MediaRecorder(); //設(shè)置錄音錄制的是雙方的還是單方的。 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //設(shè)置錄音的保存格式3GP recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //設(shè)置錄音的編碼方式 ?recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //設(shè)置錄音的保存位置? ?recorder.setOutputFile("/mnt/sdcard/record.mp3"); ?try?{ ????//準備錄音? recorder.prepare(); }?catch?(Exception?e)?{ e.printStackTrace(); } } } } }
? ??2)定義廣播接收者來啟動服務(wù)
????創(chuàng)建廣播接收者之后,按照好的編程習慣,立馬在清單里配置receiver標簽,并配置好過濾器過濾開機廣播。
public?class?BootReceiver?extends?BroadcastReceiver?{ @Override public?void?onReceive(Context?context,?Intent?intent)?{ //當手機重啟后?開啟服務(wù)? Intent?intent1?=?new?Intent(context,CallService.class); context.startService(intent1); } }
? ??
? ??3)添加權(quán)限?
????像什么配置組件,添加權(quán)限能提前完成的東西就提前完成。
?????<!--?讀取電話狀態(tài)權(quán)限??--> ????????<uses-permission?android:name="android.permission.READ_PHONE_STATE"/> ???? ?????<!--?錄音權(quán)限?--> ????????<uses-permission?android:name="android.permission.RECORD_AUDIO"/> ???? ?????<!--?SD卡讀寫權(quán)限?--> ????????<uses-permission?android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ? ?????<!--?開機啟動監(jiān)聽?--> ????????<uses-permission?android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
?????
5.應(yīng)用2_百度音樂盒案例(start/bind混合開啟服務(wù)方式)????
? ? 需求:在activity里定義播放、暫停、繼續(xù)3個功能按鈕,效果如下圖所示:
???? ?
? ? 實現(xiàn)思路:一般音樂播放軟件,在界面銷毀之后,音樂還能繼續(xù)在長期運行播放,所以音樂播放的邏輯應(yīng)該寫在服
????? ? 務(wù)里,用startService方式開啟服務(wù);點擊按鈕還要調(diào)用服務(wù)里的方法,那么又要用bindService方
????? ? 式開啟服務(wù)。所以要以混合模式開啟服務(wù)。
? ? 具體實現(xiàn)步驟:
? ? 1)服務(wù)相應(yīng)接口定義
?????//定義一個接口來暴露想暴露的方法???????? ????????public?interface?Iservice?{ ???????? public?abstract?void?callPlay(); ???????? public?abstract?void?callPause(); ???????? public?abstract?void?callRePlay(); ????????}
? ?2)服務(wù)定義??
??????package?com.itheima.baidumusic; ????????import?java.io.IOException; ???????? ????????import?android.app.Service; ????????import?android.content.Intent; ????????import?android.media.MediaPlayer; ????????import?android.net.Uri; ????????import?android.os.Binder; ????????import?android.os.IBinder; ???????? ????????/** ?????????*?播放音樂的?Service?邏輯寫在Service里,通過中間人對象返回。 ?????????*? ?????????*?模板步驟:?1.寫一個類繼承Binder,也就是IBinder(接口)的子類?,并實現(xiàn)接口,暴露想暴露的方法。?2.返回這個類的對象?。 ?????????*? ?????????*?@author?LENOVO ?????????*? ?????????*/ ????????public?class?PlayService?extends?Service?{ ???????? private?MediaPlayer?musicPlayer?=?null; ???????? ???????? @Override ???????? public?IBinder?onBind(Intent?intent)?{ ???????? System.out.println("onBind方法執(zhí)行了。。。。。。"); ???????? musicPlayer?=?new?MediaPlayer(); ???????? try?{ ???????? musicPlayer.setDataSource("/mnt/sdcard/luanhong.mp3"); ???????? }?catch?(Exception?e)?{ ???????? e.printStackTrace(); ???????? } ???????? return?new?MyBinder(); ???????? } ???????? ???????? //?定義播放音樂的方法 ???????? public?void?play()?{ ???????? System.out.println("播放音樂"); ???????? try?{ ???????? musicPlayer.prepare(); ???????? }?catch?(Exception?e)?{ ???????? e.printStackTrace(); ???????? } ???????? musicPlayer.start(); ???????? } ???????? ???????? //?定義暫停音樂的方法 ???????? public?void?pause()?{ ???????? System.out.println("暫停播放"); ???????? musicPlayer.pause(); ???????? } ???????? ???????? //?定義繼續(xù)音樂的方法 ???????? public?void?rePlay()?{ ???????? System.out.println("繼續(xù)播放"); ???????? musicPlayer.start(); ???????? } ???????? ???????? //?定義一個Binder的子類對象<中間人對象> ???????? public?class?MyBinder?extends?Binder?implements?Iservice?{ ???????? @Override ???????? public?void?callPlay()?{ ???????? play(); ???????? } ???????? ???????? @Override ???????? public?void?callPause()?{ ???????? pause(); ???????? } ???????? ???????? @Override ???????? public?void?callRePlay()?{ ???????? rePlay(); ???????? } ???????? ???????? } ????????}
? ?3)Activity里啟動服務(wù)
??????public?class?MainActivity?extends?Activity?{ //?定義與服務(wù)的連接 private?MyConn?conn?=?null; //?自定義那個類才會具有獨有的播放音樂的功能,直接聲明那個類實現(xiàn)的接口,屬于多態(tài)。 private?Iservice?serviceBinder?=?null; @Override protected?void?onCreate(Bundle?savedInstanceState)?{ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //?1.通過startService方法開啟服務(wù)?為了讓音樂盒可以長期的運行,即按下回退鍵服務(wù)不會隨之一起銷毀。 Intent?intent?=?new?Intent(this,?PlayService.class); startService(intent); conn?=?new?MyConn(); //?2.通過bindService方法開啟服務(wù)?為了調(diào)用服務(wù)里的方法 bindService(intent,?conn,?BIND_AUTO_CREATE); //?3.在activity里的onDestroy方法里注銷綁定服務(wù)。 } //?定義一個類實現(xiàn)ServiceConnection接口 private?class?MyConn?implements?ServiceConnection?{ @Override public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{ //?注意要最終是要用Iservice的特有方法,所以要強轉(zhuǎn)成Iservice. System.out.println("綁定服務(wù)成功"); serviceBinder?=?(Iservice)?service; } @Override public?void?onServiceDisconnected(ComponentName?name)?{ System.out.println("綁定服務(wù)失敗"); } } //?實現(xiàn)點擊按鈕的方法 public?void?click(View?v)?{ switch?(v.getId())?{ case?R.id.bt_play: serviceBinder.callPlay(); break; case?R.id.bt_pause: serviceBinder.callPause(); break; case?R.id.bt_rePlay: serviceBinder.callRePlay(); break; default: break; } } //?在activity里的onDestroy方法里注銷綁定服務(wù) @Override protected?void?onDestroy()?{ //?解除綁定服務(wù) unbindService(conn); super.onDestroy(); } }
??????
6.AIDL
Android?Interface?Definition?Language??Android接口定義語言
本地服務(wù):??運行在自己應(yīng)用(Android)里面的服務(wù)
遠程服務(wù)?:?運行在其他應(yīng)用(Android)里面的服務(wù)
作用: ?想解決的問題就是進程間通信,也就是調(diào)用其它進程里的服務(wù)里的方法。
? AIDL 實現(xiàn)的步驟?
????(1) 在一個應(yīng)用里面定義一個服務(wù) 服務(wù)里面有一個方法 這個方法稱為遠程服務(wù)里面的方法
????(2)在這個服務(wù)里面定義中間人對象 ?定義接口iservice.java 把想暴露的方法定義在接口里
????(3)把iservice.java文件改成 aidl文件 ?注意aidl不支持public、abstract等修飾符
????(4)系統(tǒng)會自動給我們生產(chǎn)一個iservice.java文件 stub extends IBinder imp iservie接口?
????(5)把我們定義的中間人對象直接繼承Stub
????(6)我想在另外一個應(yīng)用里面去調(diào)用這個服務(wù)里面的方法 要保證2個應(yīng)用使用的是同一個aidl文件
????(7)如何保證2 個應(yīng)用使用的是同一個aidl文件谷歌要求 ? 包名相同?
????(8)還是通過bindservice 方式去獲取到中間人對象?
????(9)注意獲取我們定義的中間人對象的方式不一樣了,在服務(wù)連接對象ServiceConnection里的onServiceConnected方法里通過
????????????????????stub 的一個靜態(tài)方法去獲取我們定義的中間人對象?Stub.asinterface(Ibinder obj);
????
AIDL的應(yīng)用場景:支付寶
▼用AIDL模擬調(diào)用支付寶服務(wù)里的服務(wù)方法: ??
? ?第1步: ?建立兩個應(yīng)用
??????
??第2步: ?模擬支付寶服務(wù)(實際上支付寶是很復雜的) ?
????★先定義AIDL(相當于接口)?
?????定義AIDL之后,程序會自動在gen目錄下生成相同包名相同文件名的java文件,可以看到Java
????文件中有一抽象類Stub,既繼承了Binder類又實現(xiàn)了IService接口。這就是為什么下面服
????務(wù)“中間人”是直接繼承Stub的原因。
???
????★定義支付寶服務(wù)
???? ?注意要為服務(wù)配一個過濾器,指定一個action,因為支付寶服務(wù)要被另外一個應(yīng)用所調(diào)用,
????要用到隱式意圖,那么就必須配置一個過濾器。
?????????????<service?android:name="com.itheima.service.PayService"?> ????????????????<intent-filter> ????????????????????<action?android:name="com.itheima.MY_ALI_PAY"?/> ????????????????</intent-filter> ?????????????</service>
????? 定義支付寶服務(wù)
????/** ?????*?支付寶服務(wù) ?????*/ ????public?class?PayService?extends?Service?{ ???? ???? @Override ???? public?IBinder?onBind(Intent?intent)?{ ???? //?TODO?Auto-generated?method?stub ???? return?new?MyBinder(); ???? } ???? ???? //定義一個支付的方法 ???? public?boolean?Pay(String?username,String?password,double?money) ???? { ???? //邏輯 ???? System.out.println("密碼加密。。。。。。。。。"); ???? System.out.println("檢查手機有沒有病毒。。。。。。。。。"); ???? System.out.println("判斷用戶名和密碼。。。。。。。。"); ???? System.out.println("......"); ???? ???? if(!(username.equals("root")?&&?password.equals("1234"))) ???? { ????// Toast.makeText(getApplicationContext(),"密碼錯誤.....",?0).show(); ???? System.out.println("sdggsgggs"); ???? return?false; ???? } ???? if(money?<?4000) ???? { ????// Toast.makeText(getApplicationContext(),"豆子數(shù)不足4000.....",?0).show(); ???? System.out.println("QQQQQQQQQQQ"); ???? return?false; ???? } ???? ???? return?true; ???? } ???? ???? ???? //定義一個中間人對象與調(diào)用本地服務(wù)不一樣,直接繼承Stub類就可以了。 ???? private?class?MyBinder?extends?Stub ???? { ???? ???? @Override ???? public?boolean?callPay(String?username,?String?password,?double?money) ???? throws?RemoteException?{ ???? return?Pay(username,?password,?money); ???? } ???? } ????}
????第3步: ?在另外一個應(yīng)用里調(diào)用支付寶服務(wù)
??????★?首先,將支付寶服務(wù)應(yīng)用的aidl拷貝過來,并且包名要保持一致。
??????★?Activity調(diào)用支付寶服務(wù)的代碼:
public?class?MainActivity?extends?Activity?{? ????????//連接遠程服務(wù)的連接對象??? ???? private?MyConn?conn?=?null; ???? ???? //怎么才能將其它應(yīng)用的IService得到呢,使用AIDL技術(shù)。 ???? private?IService?serviceBinder?=?null; ???? ????????@Override ????????protected?void?onCreate(Bundle?savedInstanceState)?{ ????????????super.onCreate(savedInstanceState); ????????????setContentView(R.layout.activity_main); ????????????//綁定服務(wù)-----------------注意這個邏輯要寫在onCreate方法里,因為它需要一定的時間。 ???????? //由于是跨應(yīng)用訪問,要使用隱式意圖。 ???????? Intent?intent?=?new?Intent(); ???????? intent.setAction("com.itheima.MY_ALI_PAY"); ???????? ???????? conn?=?new?MyConn(); ???????? bindService(intent,?conn,?BIND_AUTO_CREATE); ????????} ???????? ????????public?void?click(View?v) ????????{ ???????? try?{ ???? boolean?flag?=?serviceBinder.callPay("root",?"1234",?5000); //空指針,沒有連接上。。。 ???? if(flag) ???? { ???? System.out.println("支付成功"); ???? } ???? }?catch?(RemoteException?e)?{ ???? e.printStackTrace(); ???? } ???????? ????????} ???????? ????????//定義一個類實現(xiàn)ServiceConnection接口 ????????public?class?MyConn?implements?ServiceConnection ????????{ ???? ???? @Override ???? public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{ ???? System.out.println("服務(wù)連接上了。。。。"); ???? serviceBinder?=?Stub.asInterface(service); ???? } ???? ???? @Override ???? public?void?onServiceDisconnected(ComponentName?name)?{ ???? System.out.println("服務(wù)連接失敗。。。。"); ???? } ???????? ????????} ???????? ????????//解除綁定Service ????????@Override ????????protected?void?onDestroy()?{ ???????? unbindService(conn); ???????? super.onDestroy(); ????????} ????}
?
? ? ? 實際開發(fā)中遇到的問題:
? ? ?1.https://blog.csdn.net/sparklebirdie/article/details/50481343? ? ?(startCommand中的intent為null)
?????
通知欄的使用
1)自定義:https://blog.csdn.net/baidujiangwei18/article/details/51347601
2)RemoteView異常:https://blog.csdn.net/qq_38320839/article/details/80402865
?????????其實RemoteView源碼注釋寫的很清楚,限定了它的布局的View的種類。
????? 3)9.0通知適配
?????????一般的創(chuàng)建通知欄的方法,發(fā)現(xiàn)在android9.0手機上不顯示。
? ? ? ? 》》創(chuàng)建Notification要增加渠道:
????????????? ?https://blog.csdn.net/zj2576688626/article/details/95340701
????????????? ?https://blog.csdn.net/qq_31392539/article/details/93799917
????????????????https://blog.csdn.net/big_sea_m/article/details/83824323
????????》》開啟通知權(quán)限:(引導用戶到設(shè)置里開啟)
????????????? ?http://www.manongjc.com/article/34177.html?(推薦)
????? ?????????https://www.jianshu.com/p/ddd2c0edbba9
? ?? ??
本文題目:AndroidDay08四大組件之服務(wù)Service
文章地址:http://jinyejixie.com/article42/gpeshc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、移動網(wǎng)站建設(shè)、網(wǎng)站排名、營銷型網(wǎng)站建設(shè)、品牌網(wǎng)站制作、標簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)