开发者

Android入门之bindService的用法详解

目录
  • 介绍
  • 来看例子
  • 全代码
    • Service注册
    • Service类(坑来了)
    • 主运行类-MainActivity.Java
  • 运行效果

    介绍

    在前一天我们介绍了android中有两种启动Service的方法。并擅述了startService和bindService的区别。同时我们着重讲了startService。

    因此今天我们就来讲bindService。bindService大家可以认为它是和Android的一个共生体。即这个service所属的activity如果消亡那么bindService也会消亡。

    因此今天我们以一个比较复杂的例子,activity<->service间互相传值来讲透这个bindService的使用,同时我们在这个例子中故意留下一个坑即:在Service里使用Thread处理大事务是不是就一定安全呢?也不安全,它也会引起ANR即:Application Not Responding-安卓崩溃。从而以这个坑来引出IntentService的使用。

    来看例子

    Android入门之bindService的用法详解

    我们设有三个按钮:

    • 【BIND SERVICE】-点击后运行Service
    • 【STOP BINDING】-点击后结束Service
    • 【GET VALUE FROM BINDER】-通过Activity获取正在BINDING的Service内的值,此处我们留下了一个ANR的坑,即获取Service内的值时我们留了一个Thread.Sleep(30000)的长事务,来观察ANR;

    此处记得按钮的点击顺序为:先点【BIND SERVICE】->再点【GET VALUE FROM BINDER】->再点【STOP BINDING】不过此处你没有机会点这个【STOP BINDING】按钮,因为在GET时你已经ANR(崩溃)了。

    来看全代码展示。

    全代码

    Service注册

    <?XML version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools=编程客栈"http://schemas.android.com/tools">
     
        <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.DemoBindService"
            tools:targetApi="31">
            <service
                android:name=".SampleBindSe开发者_Python入门rvice"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action
                        android:name="org.mk.android.demo.SampleBindService"/>
                </intent-filter>
     
            </service>
            <activity
                android:name=".MainActivity"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
     
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
     
                <meta-data
                    android:name="android.app.lib_name"
                    android:value="" />
            </activity>
        </application>
     
    </manifest>

    Service类(坑来了)

    package org.mk.android.demo;
     
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.util.Log;
     
    public class SampleBindService extends Service {
        private final String TAG = "SimpleBindService";
        private int count;
        private boolean quit;
        private CountNumBinder countNumBinder = new CountNumBinder();
     
        public SampleBindService() {
        }
     
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            Log.i(TAG, ">>>>>>onBind方法被调用");
            return countNumBinder;
        }
     
        //Service被关闭前回调
        @Override
        public void onDestroy() {
            super.onDestroy();
            this.quit = true;
            Log.i(TAG, ">>>>>>onDestroyed方法被调用!");
        }
     
        @Override
        public void onRebind(Intent intent) {
            Log.i(TAG, ">>>>>>onRebind方法被调用!");
            super.onRebind(intent);
        }
     
        //Service被创建时调用
        @Override
        public void onCreate() {
            Log.i(TAG, ">>>>>>onCreatejavascript方法被调用");
            super.onCreate();
            //创建一个线程动态地修改count的值
            new Thread() {
                public void run() {
                    while (!quit) {
                        try {
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        count++;
                    }
                }
     
                ;
            }.start();
        }
     
        //Service断开连接时回调
        @Override
        public boolean onUnbind(Intent intent) {
            Log.i(TAG, ">>>>>>onUnbind方法被调用!");
            return true;
        }
     
        //Service被启动时调用
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i(TAG, ">>>>>>onStartCommand方法被调用");
            return super.onStartCommand(intent, flags, startId);
        }
     
     
        public class CountNumBinder extends Binder {
            public int getCount() {
                Log.i(TAG, ">>>>>>into long waiting");
     
                try {
                    Thread.sleep(300000);
                } catch (Exception e) {
                }
     
                return -1;
            }
        }
    }

    我们可以看到,这个Service以每秒对着count+1.

    然后通过bindService的onBind生命体里以一个CountNumBinder暴露出去,给到外部可以通过一个getCount方法来调用获取Service里当前count的值,但是这个值在获取前我们会使用Thread.sleep(30000)-30秒来模拟ANR。

    主运行类-MainActivity.java

    在调用Service的activity里我们使用bindService(intent, conn, Service.BIND_AUTO_CREATE);来启动。

    这边这个conn是一个ServiceConnection类,new出一个ServiceConnection类并覆盖里面的

    • onServiceConnected方法,用于接受bindService返回的对象;
    • onServiceDisconnected方法,用于在这个bindService被销毁时作处理;

    具体代码如下:

    package org.mk.android.demo;
     
    import androidx.appcompat.app.AppCompatActivity;
     
    import android.app.Service;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
     
    public class MainActivity extends AppCompatActivity {
        private final String TAG = "SimpleBindService";
        private Button buttonBindService;
        private Button buttonStopBinding;
        private Button buttonGetValueFromBinder;
        private Context ctx;
        private Intent intent;
        private SampleBindService.CountNumBinder countNumBinder;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            buttonBindService = (Button) findViewById(R.id.buttonBindService);
            buttonStopBinding = (Button) findViewById(R.id.buttonStopBinding);
            buttonGetValueFromBinder = (Button) findViewById(R.id.buttonGetValueFromBinder);
            ctx = MainActivity.this;
            intent = new Intent(ctx, SampleBindService.class);
            buttonBindService.setOnClickListener(new OnClickListener());
            buttonStopBinding.setOnClickListener(new OnClickListener());
            buttonGetValueFromBinder.setOnClickListener(new OnClickListener());
        }
     
        private ServiceConnection conn = new ServiceConnection() {
     
            //Activity与Service断开连接时回调该方法
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i(TAG, ">>>>>>Service DisConnected");
            }
     
            //Activity与Service连接成功时回调该方法
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i(TAG, ">>>>>>Service Connected");
                countNumBinder = (SampleBindService.CountNumBinder) service;
            }
        };
     
        class OnClickListener implements View.OnClickListener {
            @Override
            public void onClick(View view) {
                Intent eIntent;
                switch (view.getId()) {
                    case R.id.buttonBindService:
                        bindService(intent, conn, Service.BIND_AUTO_CREATE);
                        break;
                    case R.id.buttonStopBinding:
                        unbindService(conn);
                        break;
                    case R.id.buttonGetValueFromBinder:
                        Toast.编程客栈makeText(getApplicationContext(), "Service的count" + "的值为:" + countNumBinder.getCount(), Toast.LENGTH_LONG).show();
                        break;
                }
            }
        }
    }

    运行效果

    • 先点【BIND SERVICE】;
    • 再点【GET VALUE FROM BINDER】;

    Android入门之bindService的用法详解

    看,ANR出现了。

    这就是我说的坑,怎么解决这个坑,请听下回分解。

    到此这篇关于Android入门之bindService的用法详解的文章就介绍到这了,更多相关Apythonndroid bindService内容请搜索我们以前的文章或继续浏python览下面的相关文章希望大家以后多多支持我们!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜