package Ġcom . h xb reak . animal cross ing tools . services . handler Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . net . Uri Ċ import Ġandroidx . lifecycle . LiveData Ċ import Ġandroidx . lifecycle . Mutable LiveData Ċ import Ġandroidx . room . with Transaction Ċ import Ġcom . google . protobuf . ByteString Ċ import Ġcom . h xb reak . animal cross ing tools . data . source . Animal Cross ing Database Ċ import Ġcom . h xb reak . animal cross ing tools . data . source . Default Data Repository Ċ import Ġcom . h xb reak . animal cross ing tools . data . source . entity . Message Entity Ċ import Ġcom . h xb reak . animal cross ing tools . fragment . Event Ċ import Ġcom . h xb reak . animal cross ing tools . services . File Provider Ext Ċ import Ġcom . h xb reak . animal cross ing tools . utils . close Quiet ly Ċ import Ġcom . h xb reak . animal cross ing tools . utils . file To Uri Ċ import Ġcom . h xb reak . backend . Backend Packet Ċ import Ġcom . h xb reak . st un . Discover Info Ċ import Ġdagger . h ilt . android . qual ifiers . ApplicationContext Ċ import Ġio . netty . channel . Channel HandlerContext Ċ import Ġkotlinx . coroutines .* Ċ import Ġtim ber . log . Tim ber Ċ import Ġjava . io . File Ċ import Ġjava . io . File OutputStream Ċ import Ġjava . io . OutputStream Ċ import Ġjava . net . Inet SocketAddress Ċ import Ġjava . net . NetworkInterface Ċ import Ġjava . time . Clock Ċ import Ġjava . time . Instant Ċ import Ġjava . time . LocalDateTime Ċ import Ġjava . time . Zone Offset Ċ import Ġjavax . inject . Inject Ċ import Ġkotlin . coroutines . Continuation Ċ import Ġkotlin . coroutines . Coroutine Context Ċ import Ġkotlin . coroutines . resume Ċ import Ġkotlin . coroutines . suspend Coroutine Ċ Ċ data Ġclass ĠTransfer Stream ( ĊĠĠĠ Ġval Ġto : ĠString , ĊĠĠĠ Ġval Ġkey : ĠString , ĊĠĠĠ Ġval Ġfile : ĠFile , ĊĠĠĠ Ġval ĠoutputStream : ĠOutputStream , Ċ ) Ċ Ċ class ĠInstant Message Controller ( ĊĠĠĠ Ġprivate Ġval Ġcontext : ĠContext , ĊĠĠĠ Ġprivate Ġval Ġdatabase : ĠAnimal Cross ing Database , Ċ ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġmessage Dao Ġ= Ġdatabase . message Dao () ĊĠĠĠ Ġprivate Ġval Ġservice Job Ġ= ĠSuper visor Job () ĊĠĠĠ Ġprivate Ġval Ġservice Scope Ġ= ĠCor outine Scope ( Dispatch ers . Main Ġ+ Ġservice Job ) ĊĊĠĠĠ Ġprivate Ġval Ġ_ last Exception Ġ= ĠMutable LiveData < Throwable ?> () ĊĠĠĠ Ġprivate Ġval Ġ_ authorized Ġ= ĠMutable LiveData ( false ) ĊĠĠĠ Ġprivate Ġval Ġ_ lob by List Ġ= ĠMutable LiveData < List < Backend Packet . Net User Entity >>() ĊĠĠĠ Ġprivate Ġval Ġ_ st un Response Ġ= ĠMutable LiveData < Event < Backend Packet . St un Response >>() ĊĠĠĠ Ġprivate Ġval Ġ_ st un Request Ġ= ĠMutable LiveData < Event < Backend Packet . St un Request >>() ĊĊĠĠĠ Ġval Ġauthorized : ĠLive Data < Boolean > ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ authorized ĊĊĠĠĠ Ġval Ġst un Response : ĠLive Data < Event < Backend Packet . St un Response >> ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ st un Response ĊĊĠĠĠ Ġval Ġst un Request : ĠLive Data < Event < Backend Packet . St un Request >> ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ st un Request ĊĊĠĠĠ Ġval Ġlast Exception : ĠLive Data < Throwable ?> ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ last Exception ĊĊĠĠĠ Ġval Ġlob by List : ĠLive Data < List < Backend Packet . Net User Entity >> ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ lob by List ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠInit ĠBy ĠInstant MessageHandler ĠRemove ĠBy ĠInstant MessageHandler ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġvar Ġmain Channel : ĠChannel HandlerContext ? Ġ= Ġnull ĊĠĠĠ Ġset ( value ) Ġ{ ĊĠĠĠĠĠĠĠ Ġfield Ġ= Ġvalue ĊĠĠĠĠĠĠĠ Ġif Ġ( value Ġ== Ġnull ){ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(_ authorized . value Ġ!= Ġfalse ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// clear Ġup ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ lob by List . value Ġ= Ġempty List () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ authorized . value Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġauthorized Block ( block : Ġsuspend Ġ( Channel HandlerContext ) Ġ-> ĠUnit ) Ġ: ĠBoolean { ĊĠĠĠĠĠĠĠ Ġreturn Ġwith Context ( service Scope . coroutine Context ){ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(( main Channel ?. is Removed Ġ== Ġfalse )){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(_ authorized . value Ġ== Ġtrue ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblock ( main Channel !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ with Context Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} else { ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Exception ( Exception (" User ĠIs ĠNot ĠAuthor ized ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} else { ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle Exception ( Exception (" Not ĠConnected ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ with Context Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġsend St un Request ( to Id : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġauthorized Block Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpacket Ġ= ĠBackend Packet . ToServer Packet . newBuilder (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Type Ġ= ĠBackend Packet . Backend MessageType . ST UN _ REQUEST ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġst un Request Ġ= ĠBackend Packet . St un Request . newBuilder (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset To Id ( to Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġp Ġ= Ġmain Channel !!. write And Flush ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġp . await () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġsend St un Info Reply ( info : ĠDis cover Info , Ġis Accept : ĠBoolean ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġauthorized Block Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpacket Ġ= ĠBackend Packet . ToServer Packet . newBuilder (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Type Ġ= ĠBackend Packet . Backend MessageType . ST UN _ INFO _ SWAP ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġst un Info Reply Ġ= ĠBackend Packet . St un Info Reply . newBuilder (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġop Ġ= Ġif Ġ( is Accept ) ĠBackend Packet . St un Operation Type . ACCEPT Ġelse ĠBackend Packet . St un Operation Type . DECL INE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpublic Addr Ġ= Ġinfo . public IP ?. host Address ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpublic Port Ġ= Ġinfo . public Port Ġ?: Ġ- 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġp Ġ= Ġmain Channel !!. write And Flush ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġp . await () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun ĠsendMessage To ( to Id : ĠString , Ġmsg : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġauthorized Block Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbytes Ġ= ĠByte String . copyFrom Utf 8 ( msg ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( bytes . size () Ġ<= ĠMAX _ LEN _ IN _ PACKET ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpacket Ġ= ĠBackend Packet . ToServer Packet . newBuilder (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Type Ġ= ĠBackend Packet . Backend MessageType . MEDIA ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmedia Entity Ġ= ĠBackend Packet . Media Entity . newBuilder (). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . content Bytes Ġ= Ġbytes ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . to Id Ġ= Ġto Id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . current Offset Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . content Length Ġ= Ġit . content Bytes . size (). to Long () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . content Mime type Ġ= Ġ"$ APP _ PRIVATE _ MEDIA _ MIME _ TYPE /$ DIRECT _ DISPLAY _ MIME _ TYPE " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmain Channel !!. write And Flush ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġsend File To ( stream Id : ĠString , Ġself Id : ĠString , Ġto Id : ĠString , Ġuri : ĠUri , ĠmimeType : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġauthorized Block Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinput Ġ= Ġcontext . content Resolver . open InputStream ( uri ) Ġ?: Ġreturn @ authorized Block ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcache Ġ= ĠByteArray ( MAX _ LEN _ IN _ PACKET ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcurrent Ġ= Ġ 0 L ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcl Ġ= Ġinput ?. available () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( true ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlen Ġ= Ġinput ?. read ( cache , Ġ 0 , ĠMAX _ LEN _ IN _ PACKET ) Ġ?: Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( len Ġ< Ġ 0 ) Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpacket Ġ= ĠBackend Packet . ToServer Packet . newBuilder (). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Type Ġ= ĠBackend Packet . Backend MessageType . MEDIA ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmedia Entity Ġ= ĠBackend Packet . Media Entity . newBuilder (). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . stream Id Ġ= Ġstream Id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . content Bytes Ġ= ĠByte String . copyFrom ( cache , Ġ 0 , Ġlen ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . to Id Ġ= Ġto Id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . current Offset Ġ= Ġcurrent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . content Length Ġ= Ġcl . to Long () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . content Mime type Ġ= ĠmimeType ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. build () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsuspend Coroutine < Unit > Ġ{ Ġcon Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġf Ġ= Ġit . channel (). write And Flush ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġf . addListener Ġ{ Ġcon . resume ( Unit ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Ġ+= Ġlen ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . e ("$ cl , Ġ$ current , Ġ$ len ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput . close Quiet ly () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdatabase . with Transaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentity Ġ= ĠMessage Entity ( self Id , Ġto Id , ĠmimeType , ĠLocalDateTime . now ( Clock . system UTC ()), Ġpath Ġ= Ġuri . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Dao . insert All ( entity ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbytes Ġ= ĠByte String . copyFrom Utf 8 ( msg ) Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( bytes . size () Ġ<= ĠMAX _ LEN _ IN _ PACKET ){ Ċ Ċ // ĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmain Channel !!. write And Flush ( packet ) Ċ // ĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġfun Ġhandle Exception ( throwable : ĠThrowable ? ){ ĊĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ last Exception . value Ġ= Ġthrowable ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġupdate Online List ( list : ĠList < Backend Packet . Net User Entity >) Ġ{ ĊĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ lob by List . value Ġ= Ġlist ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġhandle St un Response ( response : ĠBackend Packet . St un Response ){ ĊĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ st un Response . value Ġ= ĠEvent ( response ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġhandle St un Request ( request : ĠBackend Packet . St un Request ){ ĊĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ_ st un Request . value Ġ= ĠEvent ( request ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġuser Authorized () Ġ{ ĊĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(_ authorized . value Ġ!= Ġtrue ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ_ authorized . value Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġstreaming Files Ġ= Ġarray ListOf < Transfer Stream >() ĊĊĠĠĠ Ġfun Ġhandle Media Content ( media Entity : ĠBackend Packet . Media Entity ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmedia Ġ= Ġmedia Entity Ġ?: Ġreturn ĊĠĠĠĠĠĠĠ Ġval Ġto Id Ġ= Ġmedia . to Id Ġ?: Ġreturn ĊĠĠĠĠĠĠĠ Ġval Ġneed Find In Table Ġ= Ġmedia . content Length Ġ> ĠMAX _ LEN _ IN _ PACKET ĊĠĠĠĠĠĠĠ Ġval ĠmimeType Ġ= Ġ( media Entity . content Mime type Ġ?: Ġreturn ). split ("/") ĊĠĠĠĠĠĠĠ Ġval Ġis App Private Media MimeType Ġ= ĠmimeType . get OrNull ( 0 ) Ġ== ĠAPP _ PRIVATE _ MEDIA _ MIME _ TYPE ĊĠĠĠĠĠĠĠ Ġval Ġmedia Dir Ġ= ĠFile Provider Ext . media Dir ( context ) ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠDirect ĠDisplay ĠMessage ĠShould ĠNot ĠBe ĠSplit ĠAnd ĠMime Type Ġis Ġ` app - private / text ` ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġval Ġis Direct Display Text Ġ= Ġ! need Find In Table Ġ&& Ġis App Private Media MimeType Ġ&& ĠmimeType . get OrNull ( 1 ) Ġ== ĠDIRECT _ DISPLAY _ MIME _ TYPE ĊĠĠĠĠĠĠĠ Ġif Ġ( is Direct Display Text ){ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocal DateTime Ġ= ĠInstant . of Epoch Milli ( media . server Datetime ). at Offset ( Zone Offset . UTC ). to LocalDateTime () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentity Ġ= ĠMessage Entity ( Ġmedia . from Id , Ġmedia . to Id , Ġmedia . content Mime type , Ġlocal DateTime , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdescription Ġ= Ġmedia . content Bytes . toString Utf 8 () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdatabase . with Transaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Dao . insert All ( entity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} else { ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġ* ĠWhen ĠText ĠMessage ĠLarge ĠTh an Ġ 8 k Ġthey Ġwill Ġsave Ġas ĠFile . ĊĠĠĠĠĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtransfer Ġ= Ġif Ġ( media Entity . current Offset Ġ== Ġ 0 L ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( media Dir , Ġ"${ media . stream Id }@ ${ media . from Id }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuri Ġ= Ġcontext . file To Uri ( file ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstream Ġ= ĠFileOutputStream ( file ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtransfer Ġ= ĠTransfer Stream ( media . to Id , Ġmedia . stream Id , Ġfile , Ġstream ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstreaming Files . add ( transfer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransfer ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} else { ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstreaming Files . first OrNull Ġ{ Ġit . key Ġ== Ġmedia . stream Id Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( transfer Ġ!= Ġnull ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlen Ġ= Ġmedia . content Bytes . size () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmedia . content Bytes . writeTo ( transfer . output Stream ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( media . current Offset Ġ+ Ġlen Ġ>= Ġmedia . content Length ){ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuri Ġ= Ġcontext . file To Uri ( transfer . file ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtransfer . output Stream . close Quiet ly () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstreaming Files . remove ( transfer ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocal DateTime Ġ= ĠInstant . of Epoch Milli ( media . server Datetime ). at Offset ( Zone Offset . UTC ). to LocalDateTime () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentity Ġ= ĠMessage Entity ( media . from Id , Ġmedia . to Id , Ġmedia . content Mime type , Ġlocal DateTime , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Ġ= Ġuri . toString () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġservice Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdatabase . with Transaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Dao . insert All ( entity ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMAX _ LEN _ IN _ PACKET Ġ= Ġ 4 0 9 6 Ġ* Ġ 2 ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠAPP _ PRIVATE _ MEDIA _ MIME _ TYPE Ġ= Ġ" app - private " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDIRECT _ DISPLAY _ MIME _ TYPE Ġ= Ġ" text " ĊĠĠĠ Ġ} Ċ }