热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

什么是AndroidBinder"交易?"

如何解决《什么是AndroidBinder"交易?"》经验,为你挑选了1个好方法。

我在TransactionTooLargeException从单个APK运行的两个Android进程之间发送消息时收到了消息.每条消息只包含少量数据,远小于总计1 mb(如文档中所指定).

我创建了一个测试应用程序(下面的代码)来解决这个问题,并注意到三件事:

    android.os.TransactionTooLargeException如果每条消息都超过200 kb 我得到了一个.

    android.os.DeadObjectException如果每条消息都低于200kb,我得到了一个

    添加一个Thread.sleep(1)似乎已经解决了这个问题.我不能得到一个例外Thread.sleep

通过Android C++代码,似乎transaction失败的原因不明,并被解释为其中一个异常

问题

    什么是" transaction"?

    什么定义了交易中的内容?在给定时间内是一定数量的事件吗?或者只是最大数量/大小的事件?

    有没有办法"刷新"交易或等待交易完成?

    什么是避免这些错误的正确方法?(注意:将其分解为更小的部分只会引发不同的异常)



AndroidManifest.xml中




    
        
            
                

                
            
        
        
    


MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var sendDataButton: Button
    private val myServiceConnection: MyServiceCOnnection= MyServiceConnection(this)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myServiceConnection.bind()

        sendDataButton = findViewById(R.id.sendDataButton)

        val maxTransactiOnSize= 1_000_000 // i.e. 1 mb ish
        // Number of messages
        val n = 10
        // Size of each message
        val bundleSize = maxTransactionSize / n

        sendDataButton.setOnClickListener {
            (1..n).forEach { i ->
                val bundle = Bundle().apply {
                    putByteArray("array", ByteArray(bundleSize))
                }
                myServiceConnection.sendMessage(i, bundle)
                // uncommenting this line stops the exception from being thrown
//                Thread.sleep(1)
            }
        }
    }
}

MyServiceConnection.kt

class MyServiceConnection(private val context: Context) : ServiceConnection {
    private var service: Messenger? = null

    fun bind() {
        val intent = Intent(context, BoundService::class.java)
        context.bindService(intent, this, Context.BIND_AUTO_CREATE)
    }

    override fun onServiceConnected(name: ComponentName, service: IBinder) {
        val newService = Messenger(service)
        this.service = newService
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        service = null
    }

    fun sendMessage(what: Int, extras: Bundle? = null) {
        val message = Message.obtain(null, what)
        message.data = extras
        service?.send(message)
    }
}

BoundService.kt

internal class BoundService : Service() {
    private val serviceMessenger = Messenger(object : Handler() {
        override fun handleMessage(message: Message) {
            Log.i("BoundService", "New Message: ${message.what}")
        }
    })

    override fun onBind(intent: Intent?): IBinder {
        Log.i("BoundService", "On Bind")
        return serviceMessenger.binder
    }
}

*的build.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.example.boundservicestest"
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:27.1.1'
}

堆栈跟踪

07-19 09:57:43.919 11492-11492/com.example.boundservicestest E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.boundservicestest, PID: 11492
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:448)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 
     Caused by: android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(Binder.java:764)
        at android.os.IMessenger$Stub$Proxy.send(IMessenger.java:89)
        at android.os.Messenger.send(Messenger.java:57)
        at com.example.boundservicestest.MyServiceConnection.sendMessage(MyServiceConnection.kt:32)
        at com.example.boundservicestest.MainActivity$onCreate$1.onClick(MainActivity.kt:30)
        at android.view.View.performClick(View.java:6294)
        at android.view.View$PerformClick.run(View.java:24770)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 

Pravin Divra.. 7

1)什么是“交易”?

当客户端进程调用服务器进程时(在我们的示例中service?.send(message)),它会传输表示要调用的方法的代码以及封送数据(宗地)。此调用称为事务。客户端Binder对象调用,transact()而服务器Binder对象在onTransact()方法中接收此调用。检查此和此。

2)什么定义了交易的内容?在给定时间内是否有一定数量的事件?还是仅仅是事件的最大数量/大小?

通常,这是由Binder协议决定的,它们使用代理(由客户端)和存根(由服务)。代理接受您的高级Java / C ++方法调用(请求),并将其转换为包裹(编组),然后将事务提交给Binder内核驱动程序并进行阻止。另一方面(在Service流程中),Stub会侦听Binder内核驱动程序,并在收到回调后将包裹解组为服务可以理解的丰富数据类型/对象。

如果是Android Binder框架,则通过transact()发送的数据是一个Parcel(这意味着我们可以发送Parcel对象支持的所有类型的数据。),存储在Binder事务缓冲区中.Binder事务缓冲区的固定大小有限,当前为1Mb,该进程正在进行的所有交易都共享该数据。因此,如果每个消息超过200 kb,则5个或更少的正在运行的事务将导致限制超过并抛出TransactionTooLargeException。因此,即使有许多交易正在进行,即使有许多交易正在进行,也可能引发此异常。将会看到一个活动DeadObjectException如果它使用在另一个进程中运行的服务,而该进程在执行请求的过程中终止,则异常。在Android中杀死进程的原因很多。检查此博客以获取更多信息。

3)是否可以“刷新”交易或等待交易完成?

transact()默认情况下,对客户端线程的调用(在process1中运行)会阻塞,直到onTransact()在远程线程(在process2中运行)执行完为止。因此,事务API实际上在Android中是同步的。如果您不希望transact()调用阻塞,则可以传递IBinder.FLAG_ONEWAY标志(标记为transact(int,Parcel,Parcel,int))立即返回,而无需等待任何返回值。您必须实现您为此定制的IBinder实现。

4)避免这些错误的正确方法是什么?(注意:将其分解成较小的部分只会抛出不同的异常)

    一次限制交易数量。执行真正必要的事务(一次所有正在进行的事务的消息大小必须小于1MB)。

    确保正在运行其他Android组件的进程(应用程序进程除外)。

注意:-Android支持Parcel在不同进程之间发送数据。一个Parcel既可以包含将在IPC的另一侧进行平整化的平整数据(使用此处的各种方法来写入特定类型,也可以使用通用的Parcelable接口),还可以包含对活动IBinder对象的引用,这将导致另一侧接收到该数据。与包裹中的原始IBinder连接的代理IBinder。

将服务与活动绑定的正确方法是在Activity onStart()上绑定服务,然后在onStop()上取消绑定,这是Activity的可见生命周期。

在您的情况下,在MyServiceConnection类中添加方法:

fun unBind() { context.unbindService(this) }

在您的Activity类中:

override fun onStart() {
        super.onStart()
        myServiceConnection.bind()
    }

    override fun onStop() {
        super.onStop()
        myServiceConnection.unBind()
    }

希望这会帮助你。



1> Pravin Divra..:

1)什么是“交易”?

当客户端进程调用服务器进程时(在我们的示例中service?.send(message)),它会传输表示要调用的方法的代码以及封送数据(宗地)。此调用称为事务。客户端Binder对象调用,transact()而服务器Binder对象在onTransact()方法中接收此调用。检查此和此。

2)什么定义了交易的内容?在给定时间内是否有一定数量的事件?还是仅仅是事件的最大数量/大小?

通常,这是由Binder协议决定的,它们使用代理(由客户端)和存根(由服务)。代理接受您的高级Java / C ++方法调用(请求),并将其转换为包裹(编组),然后将事务提交给Binder内核驱动程序并进行阻止。另一方面(在Service流程中),Stub会侦听Binder内核驱动程序,并在收到回调后将包裹解组为服务可以理解的丰富数据类型/对象。

如果是Android Binder框架,则通过transact()发送的数据是一个Parcel(这意味着我们可以发送Parcel对象支持的所有类型的数据。),存储在Binder事务缓冲区中.Binder事务缓冲区的固定大小有限,当前为1Mb,该进程正在进行的所有交易都共享该数据。因此,如果每个消息超过200 kb,则5个或更少的正在运行的事务将导致限制超过并抛出TransactionTooLargeException。因此,即使有许多交易正在进行,即使有许多交易正在进行,也可能引发此异常。将会看到一个活动DeadObjectException如果它使用在另一个进程中运行的服务,而该进程在执行请求的过程中终止,则异常。在Android中杀死进程的原因很多。检查此博客以获取更多信息。

3)是否可以“刷新”交易或等待交易完成?

transact()默认情况下,对客户端线程的调用(在process1中运行)会阻塞,直到onTransact()在远程线程(在process2中运行)执行完为止。因此,事务API实际上在Android中是同步的。如果您不希望transact()调用阻塞,则可以传递IBinder.FLAG_ONEWAY标志(标记为transact(int,Parcel,Parcel,int))立即返回,而无需等待任何返回值。您必须实现您为此定制的IBinder实现。

4)避免这些错误的正确方法是什么?(注意:将其分解成较小的部分只会抛出不同的异常)

    一次限制交易数量。执行真正必要的事务(一次所有正在进行的事务的消息大小必须小于1MB)。

    确保正在运行其他Android组件的进程(应用程序进程除外)。

注意:-Android支持Parcel在不同进程之间发送数据。一个Parcel既可以包含将在IPC的另一侧进行平整化的平整数据(使用此处的各种方法来写入特定类型,也可以使用通用的Parcelable接口),还可以包含对活动IBinder对象的引用,这将导致另一侧接收到该数据。与包裹中的原始IBinder连接的代理IBinder。

将服务与活动绑定的正确方法是在Activity onStart()上绑定服务,然后在onStop()上取消绑定,这是Activity的可见生命周期。

在您的情况下,在MyServiceConnection类中添加方法:

fun unBind() { context.unbindService(this) }

在您的Activity类中:

override fun onStart() {
        super.onStart()
        myServiceConnection.bind()
    }

    override fun onStop() {
        super.onStop()
        myServiceConnection.unBind()
    }

希望这会帮助你。


推荐阅读
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文详细介绍了解决全栈跨域问题的方法及步骤,包括添加权限、设置Access-Control-Allow-Origin、白名单等。通过这些操作,可以实现在不同服务器上的数据访问,并解决后台报错问题。同时,还提供了解决second页面访问数据的方法。 ... [详细]
author-avatar
如此而已628_722
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有