<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # 1.Service的創建 1. **手動創建** - 新建Class文件,繼承Service - 在AndroidMainfest中進行注冊 2. **使用AndroidStudio進行自動創建** **AndroidMainfest.xml** ```java <service //Service所在的類 android:name=".MyService" //Service是否可用 android:enabled="true" //是否可以被其他應用訪問 android:exported="true"/> ``` --- # 2.Service的生命周期 ## 先介紹一下Service的生命周期函數 * **OnCreate()** 當Service被創建時調用,在整個生命周期過程中只調用一次 * **OnStartCommand()** 當在Activity中調用startService()時被調用,一般用與Activity無關的Service,如播放音樂,下載等 * **OnBind()** 在Activity調用bindService()函數時調用 * **OnUnBind()** 在Activity調用unBindService()函數時調用 * **OnDestory()** 在Service銷毀時調用,調用該方法代表這本次生命周期結束,再次啟動該Service時,需調用OnCreate()方法 ## Service生命周期的兩種模式 ![Service生命周期圖解](http://upload-images.jianshu.io/upload_images/13971762-a9920d73aa10519a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 由上圖我們可以很清晰的看到,Service的生命周期分為兩種,**綁定模式**和**非綁定模式**,除此之外,還有經常可見的兩種模式的混合使用,只要我們把這兩種模式理解清楚了,相信混合模式也不在話下了 **非綁定模式:** > onCreate() -> onStartCommand() -> onDestory() 通過Context的startService() 方法啟動一個Service,執行OnCreate()和OnStartCommand()方法,再次調用startService()則會再次執行OnStartCommand()方法,不管執行多少次startService(),只需要調用一次stopService()方法,Service就會調用OnDestory()方法,來結束本次服務; **綁定模式:** > onCreate() -> onBind() -> onUnBind() -> onDestory() 通過Context的bindService()方法綁定一個Service,執行OnCreate() 和 OnBind() 方法,再次調用bindService()無效,直到調用UnBindService() 方法,執行OnUnBind() 和 OnDestory() 方法,結束本次服務; > > ==**注意:** 可能存在未調用onBindService()方法就調用OnUnBindService()或者調用一次onBindService()方法調用兩次OnUnBindService()方法,造成 *java.lang.IllegalArgumentException: Service not registered:xxx*的異常,可能導致程序崩潰== > > > - [x] **解決方法**:在調用OnUnBindService()進行異常捕獲,對異常進行處理,最后給予提示信息 代碼示例: **MyService.java** ```Java public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind "); return null; }; } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate: "); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); isRunning = false; Log.i(TAG, "onDestroy: "); } } ``` **MainActivity.java** ```java public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button startServiceBtn; private Button stopServiceBtn; private Button bindServiceBtn; private Button unbindServiceBtn; private Intent serviceIntent; private static final String TAG = "MainActivity"; private ServiceConnection serviceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG, "onServiceConnected: "); } @Override public void onServiceDisconnected(ComponentName name) { Log.i(TAG, "onServiceDisconnected: "); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); serviceIntent = new Intent(this,MyService.class); startServiceBtn=findViewById(R.id.start_service); stopServiceBtn=findViewById(R.id.stop_service); bindServiceBtn=findViewById(R.id.bind_service); unbindServiceBtn=findViewById(R.id.unbind_service); startServiceBtn.setOnClickListener(this); stopServiceBtn.setOnClickListener(this); bindServiceBtn.setOnClickListener(this); unbindServiceBtn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.start_service: startService(serviceIntent); break; case R.id.stop_service: stopService(serviceIntent); break; case R.id.bind_service: bindService(serviceIntent, serviceConnection,BIND_AUTO_CREATE); break; case R.id.unbind_service: try { unbindService(serviceConnection); }catch (IllegalArgumentException e){ Log.i(TAG, "unBindService: "+e.getMessage()); Toast.makeText(this, "未綁定任何服務!", Toast.LENGTH_SHORT).show(); } break; default: } } } ``` **activity_main.xml** ```xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/start_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="啟動本地服務" /> <Button android:id="@+id/stop_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="停止本地服務" /> <Button android:id="@+id/bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="綁定本地服務" /> <Button android:id="@+id/unbind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="解除綁定本地服務" /> </LinearLayout> ``` ## 運行截圖 ### 非綁定模式 > **為驗證多次點擊效果,點擊了5次啟動(綁定)和3次停止(解除綁定)按鈕** ![非綁定模式.png](https://upload-images.jianshu.io/upload_images/13971762-017b4c86f882c73b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### 綁定模式 > **為驗證多次點擊效果,點擊了5次綁定和2次解除綁定按鈕,發現第二次點擊解除綁定按鈕出現提示** ![綁定模式.png](https://upload-images.jianshu.io/upload_images/13971762-f84e0c40657c73fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) --- # 3. 跨應用啟動、綁定Service > 相信在第一小節Service的創建中大家已經注意到了Service的一個屬性: android:exported="true",我在上面也給大家標明了注釋--是否可以被其他應用訪問,那么說明了Service是可以在不同的應用之間使用的,這也符合了我們所了解的,Android四大組件都是可以跨進程訪問的(在通常情況下,Android的一個應用就是一個進程),那么我們該如何操作呢? **步驟如下:** 1. 創建一個新的Module--AnotherApp,將MainActivity.java和activity_main.xml拷貝一份 2. 對Intent的定義進行修改 ```java Intent intent = new Intent(); intent.setComponent(new ComponentName("com.duoshilin.aidltestapplication", "com.duoshilin.aidltestapplication.MyService")); ``` > 下面是源碼對ComponentName(String pkg, String cls)的方法介紹 因為是跨應用的訪問Service,所有我們不能直接通過平常使用的方法去啟動的一個Service; ```java /** * Create a new component identifier. * * @param pkg The name of the package that the component exists in. Can * not be null. * @param cls The name of the class inside of <var>pkg</var> that * implements the component. Can not be null. */ public ComponentName(String pkg, String cls) { if (pkg == null) throw new NullPointerException("package name is null"); if (cls == null) throw new NullPointerException("class name is null"); mPackage = pkg; mClass = cls; } ``` > String pkg 指的是要訪問的Service所在的包名; > String cls 指要訪問的Service的完整類名; **這樣我們就可以跨應用去訪問一個Service了,是不是很簡單呢?下面我們來運行一下看看效果吧!** ![image.png](https://upload-images.jianshu.io/upload_images/13971762-6b9000b48ff64fa2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) > 要注意的是,這個時候我們還是要在原APP中去查看日志打印結果哈! --- # 4. 跨進程的Service通信 > 在上一小節中,我們訪問到了其他應用中的Service,但是我們訪問到了之后應該干什么呢?當然是進行數據交互了,哈哈!不然我們為什么要去訪問他呢?(這里我就不說是跨應用了,專業點,還是跨進程吧!) 在這一小節,我們會涉及到一個新的知識點,AIDL(Android Interface Define Language 安卓接口定義語言),在AndroidStudio中我們可以創建一個AIDL文件。方法如下:在Android項目目錄結構的src/main文件夾,右擊 -> New -> Floder -> AIDL Floder,來創建一個AIDL文件夾,然后右擊該文件夾, New -> AIDL -> AIDL File, 即可創建一個AIDL文件。準備工作做的差不多了,下面開始進入今天的正題: **1. 對MyService進行一些改進,為了方便理解,還是把整個文件放上吧** ```java public class MyService extends Service { private static final String TAG = "MyService"; //要訪問的數據,默認值為"default" private String data="default"; //判斷該服務是否正在運行 private boolean isRunning = false; //線程池,不了解的同學可以去了解一下,這個東西對Java來說也是挺重要的 private ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(1,1,1,TimeUnit.MINUTES,new SynchronousQueue<Runnable>()); //定義一個接口:當Service在運行期間每隔1s打印一下當前的數據 private Runnable task = new Runnable() { @Override public void run() { while (isRunning){ Log.i(TAG, "當前數據: "+data); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }; public MyService() { } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind: "); return new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public void setData(String data) throws RemoteException { MyService.this.data = data; } }; } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate: "); isRunning = true; //啟動線程 poolExecutor.execute(task); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); isRunning = false; Log.i(TAG, "onDestroy: "); } ``` **2. 創建一個AIDL文件,內容如下:** ```java interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); void setData(String data); } ``` > 那些自動生成的內容我們暫時就先不看了,可以看到的是我增加了一個setData(String data) 接口,用來給Service的data變量設置值 **3. 增加新的控件,以便查看效果,重復代碼就不在這里貼了** **activity_main.xml** ```java <EditText android:id="@+id/edit_data_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="這是另一個應用中的數據"/> <Button android:id="@+id/save_data_btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="保存數據"/> ``` **MainActivity.java** ```java public class MainActivity extends AppCompatActivity implements View.OnClickListener { ... private Intent intent; private IMyAidlInterface binder = null; private EditText editData; private Button savaDataBtn; private ServiceConnection serviceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG, "onServiceConnected: "); //新增語句,將service轉換為IMyAidlInterface的binder對象 binder=IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { Log.i(TAG, "onServiceDisconnected: "); } }; @Override protected void onCreate(Bundle savedInstanceState) { ... intent = new Intent(); intent.setComponent(new ComponentName("com.duoshilin.aidltestapplication", "com.duoshilin.aidltestapplication.MyService")); editData=findViewById(R.id.edit_data_input); savaDataBtn=findViewById(R.id.save_data_btn); savaDataBtn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ ... case R.id.save_data_btn: try { if(binder != null) { binder.setData(editData.getText().toString()); } } catch (RemoteException e) { e.printStackTrace(); } break; default: } } } ``` **4. 重新啟動兩個APP,點擊并查看效果。** ![image.png](https://upload-images.jianshu.io/upload_images/13971762-f99d11d82222353b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) > ***需要注意的是,我們需要在綁定模式下才能修改數據,非綁定模式下我還不知道用什么方法可以修改數據,希望大神指教!*** # 5. IntentService的使用 # 6. 前臺服務的使用
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看