From 1601787ecfa009fa813d721e73e9f8618476d11c Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 10 Dec 2019 09:13:32 -0500 Subject: [PATCH] Switch back to Blessed library after bug fixes. --- Ble.jar | Bin 11121 -> 7134 bytes BleConnect.java | 293 -------------------------------------------- BlessedConnect.java | 275 +++++++++++++++++++++++++++++++++++++++++ README.md | 2 + ble_android.go | 86 ++++++------- blessed-full.jar | Bin 0 -> 78587 bytes jni_android.c | 38 +++--- jni_android.h | 3 +- timber.jar | Bin 0 -> 8434 bytes 9 files changed, 341 insertions(+), 356 deletions(-) delete mode 100644 BleConnect.java create mode 100644 BlessedConnect.java create mode 100644 blessed-full.jar create mode 100644 timber.jar diff --git a/Ble.jar b/Ble.jar index 73c9293ef6ef14c9cf6658ec8ef85b26cbb0a05a..4c6f7bd86c038637f7a78f3f16837ecd5cfa058a 100644 GIT binary patch literal 7134 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

XSi%HLA>XAjzhIeZ(Y_S1$Y^|W-*xRR&3T%1 zO!h(6AbFFAT_mGhvoN~v2yuLC-?+BFxSMniV_r$Mt+x#(t zA0?=2<+n9K@04();PoXok;Ae~*iy;3BTIEHO3pG<+m=WQBtQeLPs|ENo))x7v8X^V zs6`tCIp}|>O708ZJBMt%wM<{J%Mhc@cv-LW$Qyby0_`Qq?JG-7~eP6ULmZMvijQQP3ib$ig@4D@${|6<&brx7I>a&hJ zp8Z;^14MU!=p(Q>T@=0{`df@6FPXWiy` zkXK9+sy~4KiXn-UQ<%@`uLp_v$Y8QQF`;S`llxUM-_Osf-1z3%Fxb+->HA5tLUe+D zZxV4}Tjv^@3GArBRHxlHp=NO(*S%~4{SsyF00#?ZvufioM~xfN$G!X(Ez7y*L+f9H zCLVDfxpQke-7*) z8>o+M(%AWKcMA~Q-4op1f(H$d;M&36-5na5Ai;x&;O_43K^uo)m(1jQCz<=r z{CMx~)oYzzz4vqKoO-Hi*RDrd4hk9@0v;Y7qE|Xh3E~$+fPjWjkWd$4l2MdodFY3L zfPzq#gMiwz1i38*xttd^d zs1$#?hs4wOM=KB^Af8(G_eX$w`q$Bk<)0nk{&aA)b^RA7q`#cZE&mM-?RQ6GE3-dP z|NpO-{C_)(TA7L2+Sr(xIKALwHnB2tbc|G0P+Aa1_e=-b8|xXrM9L3@jvz!XcHhl^ zR-;NOoH$M)G9~+!?~-17^GNoR|3+UL<^}3Kq#naHUx;=xJq==#AcxoO-SVIXi!HMk z6d?S9KWjA=0g1aTz!4+f0lTe!nF%T`fxAOVtmACqhQ3geKuLJ!`BlOkYce_6HnzZ@c9fBPqZ!mGD=v zt>pwYLcyuwP9qY^TAEj38q}Mwr|ZU@owD zO|avd`WV-$3|p+M&1}IjvvzLpGQdH9itRX}8V*|92w#n)hlP>Nl&G1#Zjoui1$zyK zTw*9uRm*d>n3BXfeod1O+SQ`zlp{!M$Qmigv?F%i$Tp9vsUYKyRs3t#3vEQ<`1fJD zENORUkLf`Yu%1JQACl^ip=UR}CcB)Q`}!P|bo6IjK}*=h8?{_1ut|1p!iZ8R#3JLu zgalA{_I){sZ;X0_M?DW3MlzqDYCz3Y46-^(+la89dXW$mZ~0Qu$I#>{7QfziSiyTK zM!#z7(oj7lRqEW%3c6BIa#Ka^k4GZ6du_#!YxEHnS^na^Kr`1ow(O(xYXsfG*y9^j zzJoys$# zh#EYKBK1)$h|YW=41=s!I}}Q`9kQcD9V?e3A^{*i9MJ zpkRZs*ws-7rDX7s6Y&hr(OF0{SR*^_ZC_F?GpA@^;>6RghZD!3~0SNf**Y18=kEW^gWoSE>7 zIgfWxKe%b#l|!ZQ#7h(C|DK!de{$1PZC`al8T|pZ6cnH?3ynSIfbjxG9{ohe`Qs!# z3DTeztohwW2DP~?>$af-Vslt@8(Qp1FxsjZpN*(WaCo1o>u2-wmAU(y{aZAM0l;*y zpv`W5L^>a~BmNAVuMCM=eZCQYFab#&Te^Q@p)7wlYk`qL2T71Y&0)_(II>Bk7T>MI zisfy;B}}_Eg1ANy&`u+DFzY+8Jc|Rn^l>(^7Qag48$yt85Lwv8a8FVQH(x5-c^^2^ zF0e)Fv}$Ss>FmO?Uv^xkDKCsq7!u(Nx3xYe4w7F;Mt)mIYnzKBbJQTHNr;QG*cBJ#4hwY8 zHrfLfYK~&a%GM}YyXJ@WxF&|+AC$%3_w;V}m~*=(vWR_Y(4H&#T3)6({btI*0${jG zPRcf@cOV@iem6VPY9h#{+^yDFf^=-?7TQ)AkFNnm+C%X+MKE%=UnXy9y6AEY2?|qD z)6aA5g{;(#??j9>>^9q=P9(Gy&8pFYWpPL=bM{oi9x~<58%7jK-9lMJ^o|$}{(Xf$ zrF{#Et^!oF!mn%I46_!8Aph$qV0OD|n2z6bvsVSfZmLPc`mZ~ypM_ULYkxAB&t2-9 zpoc6`mhKJ&k$#6Y@>@fcQ9IAJIB&QqH*{PXb&Sz639(?YH%#1Rm2A93G2Mmf9*Rg6 zYR|7j3f|>%4Boxhr+~)ssV!vd;u0 zB@t*z7Xz(6fJSV8P}YQ)kK6Q#vIPGJ%5wfm*-W(so2ThiXabtW9+{1hvohS6^^g{qBWY z$0B}WJshKZVWdkmJj0TS(^n=@&y<3&Q9{c+?tWJjjiy*e%E_?tibG8bZw{7laiNK+ z;Az2*Op+TB_Orh|JIb>E< zt22)*B|xE$ZKQ?;e;atAGA(%p3+2nz{w;QXQ(i39%p~;y(||-^vxOG(J}dUU%LB2v zg$@l8PdL@$@q<+UvTpm5H);nxnFeILj55Bacd8QjS&IVnV3zUZnse9neT`Di10JKt zCJtJ3X%FeBl`cHm1=}YEm&z8jd8tx|H!6=2SPN&ukI%Q5=X;eqQvGwS8LP_A%=m&C zBIXA_qzLg`UoM^#w)~OcMIR_Cc0R4JCQmusf4jnR|4E5b&G(L28u(td3XR`f+{r1> zE#z7gKJxephhO@QF3st&o`<&ve8lBqyP}GkU2H68Fbr^MqRh9K>>Gr z3(4+b9&mdW9J%Q#18aFr1l%t(J|Ev^?07D_t_+oXdwOHF+US*t=T}ZsUhQ?Q$c+BLjrUF`NUPZmMh8k_2WTw^7P>yQ58z4cWK_wb55I+(YC6 zVrQ<`WW5$|)0Ao@u+mbim?$M$GmdnU(#fstU6dV{vH*I9uP2!JxIhZ-G3-%&0G)Q7 z_HUOFv6Go19Wpu`jim)IIG14F4b(@NBTllXl~U<1aTCu-&fI6Vl~r z4lC}#Ap_;CWm*qustFsOZ3|-9{QGS z^EOffKh!k6n>%RGFpY5x?4z_HS`H= z{C2$Yi=B;HwORf%rj!$y*Sl)+6f3m+Oj`_TKHNg3>4R^j&M$lF+_8~jqAtd+Wuu|W zYI0ce1cswinhuqOnvnu=n zf}(un?(TK}aDtFbRrpMbfY>kN_FQ9O6aZQ0yMiMr5ovF|JeZA$TH-?%i~~$)ng={T zIh~_1FK#z4K*!zDGgbXei;o#M0EtoPOWfhw+=xe?@p%^%)qUp#eVl2FZLKx|yEGGQ zCKz`*Uxy>8mg+5)xJ_|YS`J+!*=zfg9uOR*Yneu62TCiI^(`L4m^C(%# ziROn%1M7NGc$dZYH+<#L<-FyR_663N6-**!J^y#a`n+!fqy9O5m zOu?eTa7Roc-Yhe{9p%U~t&ZloFr-=E@VnR(dbbn8?_k)dH3cvC<#vLmA)4b==ca+o zs}s_ftv%Q1Z&oSwwyjXJR|P!6-d`iXT6esQUfdG3y!#ZtfuW*QjfOXVi}qvTWG_A@oq1X`;h*-u|LrWv_A}R0 z)qjsAf-MxU@Y!W4g>#;}NaGg6qAE-m7=SBb;qNP~9ujxe_g0#^grhSDrvY3%yx)^J5|N;fyb5JC`%I5Hy7gvj$R-Q=F5;v$OWC;K}Z?$Q^D2R`s`n zB}iStzG1#;sS6syk^n52=F<02hbe@*U z)k|oLLopGJ9^RR8>N<}VOUR)z*fVIpAFBZXKhwoej3=S4N4y$SQr0=M!dkDdBY7Cp zQyD_gUsO%zz;*cwtsnqMz#?}qUKAJ!r;|z4;g8T^vr#TmJ#pvB7Fs$B?#+Oc90uKt zjj6opl(Bf|`$A?|$M^gb%=fhy0eTG?I?rh1Uo{f)xrGD7moQ7Cb{BH>P7MsmcfL0I zZ7n^2jF;UEHuhy7&8_$C7b=oTsMa}W4s}Fe@Q$pZ>gwZElsSy>iRKuhnFVFgbmC^2 z;WyIuW(oZ0bjJOJsgF-frrPFeG>RO_x8tV z??OKIP{Q`ufP16ORdcn0J#!7s+o!D->DF0tIEn+m(5nZmi!&Iv@+06lSR0 z$BpnLgvhy9y%R*%UA!HR5g^3p)qqR1-k&zR?hXp^2%`I9Uk#+i0?}g9e*d?Z7uW0L6fPu9l}DKlY}RE9?@3kmillVBe`yMV~duE2hUT za~N5B6)Tfxv?cp7Op{Z=rE2z!=v(wcz51Y&QNowrxNo_xaNBT)W8NPMo1pe%Sb|CU zTMXgftgRA#;Bmb`Ud5f`v=%ryDwc~q`pOc0n=*X<0QZBDRopUHVoz+8{6FOHJpYf8 zf9CJ$=|nRz%KcOUa&ij$^>|m1lfe`(;ITDiMV>)p+7h{M)u+^$mQOt3suH22c|ec_ zrf|`HkR_DMBFN@*)FwMTe)Y;55)hHek83BDUK`4PlvW?!3NK_vU-k=RB z(-yy8Pbi*O-0@B=7b$A8kE`ZrI1Xq0eB~mu?XUga`7Mg~P~zSx?~&splCwVXafwmT zXli5YPD47W0lzmHgA>YLju>##>Rl@2DTq%$5%VhwC!Kp_F3NZ2_nk|EaE^7uDh@4q zcahKILaZVM?IbVxlX@hSl$l18+$Ej*BbDjiKSE9I!FLzPG-wYJjR}Fu>Qx3?LUlJ8 z0&2h&tE}^NfQM&47}GQnCcN=9hmHJedQbLmHPWBSy%v(5?vC>#8D)L)Kv#E_?`nY+ z79;et27tl2u7kNRzRFk5nj zde>DE&AF?ePPg6@?wvSm-vsTRDBwH-S6^v($oa#u&|b5k7={a8ifk^`t&sn)#*96c`B4g;m}wJlx-gs;PTq&C>0Bj(IjcsE5YLXfESi2l_?*} zY6Lj=V?XYh2Ca(Qb?YSo85F3HcTyNBkoP|$SBmdfp3`F$;`ys^pd(5mI0dZ=&IvfR zlfhrZ!F30@*%BS0WUQlkiRQE5Dx}D}^Y^OC^2&x*Oj8r=lkDyt9h2<8HRiGjhycT2 zG*B|IV~3|nPFfvC_4r`{4cm#ULbafT+QvQGq)i3!8+Cy~0aN#q&ut?s++n(>N6ax- zi*hWtg$cub7t^HrOU&v5@{G<{ft^c$v{i5yHFA5}gWV*)v|=>TiCWtUe0gD|MY1KV z*baR9VtC1gjCb@L9eN@p^_SbH2isPUC`6`a#5lM<)vE51PC1#S!cDHY6jMm4Og*2b zMJC`9r3SX?4@Qt~i1M0hJ*x?|qZrV5lOPvS2PkGFT~6}Bz3SoQRrX6XOwbAh0-|)Hs!_U>|k>dUwve8dg(E5v)mm+(2UN_ zfW zsNu#bUQVA3T;q_Cb;k3Pc5LvIw!t|G(huo^<@lGQgPrdP9`t(3*I$w(+m%OUcMv%@ z5!k-4(o^mD?y^>&yMYG|m-yy_ci$gcWlB%Hah9m-#6#~ST;M-hw7~;T4@g_A^Di3| z+OpY9FSgS$QPN86y4<=-95u$OF%8u@7zYJ*L^>MDt*XxyEwimumig+syU)IBlmLqH zlYFGi(5=$rC&@2cXFuGNl6v-0acOfRwiAX~19ygl|3bOEcW=TT<7)TXdU51(TcEws zM$Ku!B~+(w&q+S4i0OuKE~U(_-E0OL@oQ8i`@72fHJN7f zJ@YC&6e-&WQ*+6&MPs?-kr^WRh>IIIx1R5Cp85s#xf9=bFV3v%Si`}AHK29=%p6FP z}6H4Whr6e+jxJ*CzgcoelU13gdh4&k1NB}PTG_!Qg!b7sS7tao&w#NQ)51<}aOqUm7+`RLrZgK6^fQe`cE* z@SZ&>LeXmC2E{H3i7oS}^`3u8rkn=wW(ubRXQLgwrx-+u*p|QgO98a=zw7Z~^&YbvUM10(` z^lY=}4bejL54xF@OHNWazWEwg<3Rvh>{B#inIgZFbeKaMLlm_XH)I z-%Sk2zusW3U|im()y&0lSL1tYj0szFbBRKgH(fJE7rj{==t>bRwVQ#_C}1c~t+c%q z0>hKUvq6Eh9P8G%%6dB-O#PnSKsb z?M#quFI+iz&V3T8cPBjmB{g{|`9*)mc_{Czc=#{Lo~0}RoUGW-`3l`869iEE$(Lr$ z(ezA?m_Puadwx*tD3EiYx!2(!Vy52Mm|6Q!0AL7CXc@_7w(C)Jy+FI_KOALxl}+%C zi~%A4=<|~CMq0RiRFg+Sl9^{>f#C*$Rfj4OaM2Bp<$HUm{FrQyl?}_rAf4_e8P;?`CF3FI$w+=4gN~2b+|huv zG|3EI)!FZidY@;vjr^?Xtg^dMr;EI*=>pTsfkwCjLUi?H;z*QSh~v%x$yAq~koc2y zC9vI&GeAmcXl67{biWrzoz*g(YH}{C{b)dI-(E0MD35CR(uXn-b%gj*zebRO+vRf| zB+L6HKiTRkYiq&zKqw1yIad>Och+_RzEITV8pY*uT>u^`$1#SUB;N86d`lNRqO4bh zdm^C=RLcu%bK*^dT978^11&?lKH@Eln7y8F-eznGt{JX&d7yfj#*|dx@!?$Qp%FXz zZ0AQ3^odzIxSJNW#k6*&CjVfE1h zzSG`mEp|?1{7#~+5oD!No9{YLj`@WtG>J7Eem|9k(R%HJi(5ulT2r75E})z$2O7k_ ze7u^;{UCEfd!?J6CFg&&-FhoYC2z|V@PPm6f;T#AwE}>t3s#5ynqa>YxT24EuZ6l~ z3v4Mv{~k*$>N_xF+B4~zvVc8+uY6+4ula*{^cqeq zhJ#$9G*@Ak$3{+e&$OahatPma!g?SGfXx*7-UMc&z;Enlz_zp%9j7NnTDe~^6l#KR z%Y{|Ia4e1oSY(4&v(#iJEFrFX3PTwESXpWJp81hXiDwubLSPHt9#=Gl!py3sBv#= zd52^Y%6T(hzP)2bno?=%+p_+F<`r|-J0Jhe;DazcKAx|gIj`0i&)C27&Y;G03=>dU zA3(H|t$nTa$~MA>tdEZ^;P{Th$4|WMpYNPM;*^l+L^~zxJm+3nR93BH`AzxLlm;5G z3FPmncC&!p=&->s6$Mwi8ls(cVn|(3PZ73LEfm2O6JMapM=v9WqmdKqRIN%iZ^?Ce z+7v&%PRnN>G2Ny#RUi4zPGD*sb>2|B5+$F9_d_A#Lkjj?sNXB9o1IPND@<92H$m~f zE5Qtm((&2qr4RRj**&s0xRM8zFWwPK<>#+&pyeJ#UUn6#vJH4xqFL8|cKjB^SJ*J5 zw6o46pJu$vSrlHU!>xP4X?;2@LMQHt;)vusr)Cz7_uMngSw7yz=&BEr<&1L(SdD%V zj5xuMIA&m;K2fd9x4lKEDX1{yNJ}SvXXGNC1`z0phHmQaTz=O>tcjEBO*n#G5sf?7 z!|&CJ7;erd;4c@5NL**KVteK3a$N16y+l@XOaG<3+P!?KB~fW?p}+se?Sb?G&iNJ0 zkFBLcBMmw#Dg*>H`F~#%<@$4TnW?7#M|n(a099Y}%e0a(#y)*Mel6jJglKLgHMK+} z`f|aSco(Boa)Hm&EoOeA9$>iZya-oDnGUEBo2skj2FKz1wAAdD=0^xHcJw>2T?bsx z5MkL`l9KUok036ujU%JOq8a#rl|v=i2xx94IGzWHnXAtpxYl6)qC=NDiwCVcqW+c# zA6Iv0RnrB(SU*!X$c;tqRKH;*xvTa$zF0mjPG1t#jcy|&<_)zY(S=MvjsA&D%ubE0 zgEc$XY=TRnT2wy76*_ET8yf3=3H1?NNX6h7Vuc^Kv)x;xF^-^Brc?(?D=SpUVkYa~wdlFZ+>QowkU6^d{7c1^b@f2&t^I!FdkBfR{Bj5evY%>5Fu!%W z@kx#ed&a&PPuZ0z=&0fhmFpG1lO+`6BVg}=l7dZ_a|9O#KW{|xu@ zxcl#LzaAI-4%h$Gt^W-7^IYifaKF}ie}`+q_&2zpCk}sy`?V1GJDkeXsQTyD{VW&% z9q!l3|3~%kFZ0L!7q~yC`@e(zI&=Kqw&fT90`}tP>Y*$L1N-Ct=uaQ(r@7^b`p2*T E0oLy<4FCWD diff --git a/BleConnect.java b/BleConnect.java deleted file mode 100644 index b4e4d69..0000000 --- a/BleConnect.java +++ /dev/null @@ -1,293 +0,0 @@ -package st.wow.git.ble; - -import java.lang.Runnable; -import java.lang.String; -import java.util.List; -import java.util.UUID; -import android.util.Log; -import java.lang.Class; -import java.lang.ClassLoader; -import java.lang.reflect.Constructor; -import android.app.Activity; -import android.app.Fragment; -import android.os.Handler; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGattDescriptor; -import android.bluetooth.BluetoothGattService; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothManager; -import android.bluetooth.BluetoothProfile; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.Manifest; - -public class BleConnect extends Fragment { - BluetoothManager manager; - BluetoothAdapter adapter; - Handler handler; - boolean wantScan = false; - - final int PERMISSION_REQUEST = 1; - - final int REQUEST_ENABLE_BT = 1; - - public BleConnect() { - Log.d("gio", "BleConnect()"); - } - - @Override public void onAttach(Context ctx) { - super.onAttach(ctx); - Log.d("gio", "BleConnect: onAttach()"); - ctx.registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); - manager = (BluetoothManager) ctx.getSystemService(ctx.BLUETOOTH_SERVICE); - adapter = manager.getAdapter(); - handler = new Handler(ctx.getMainLooper()); - if (!enabled()) { - Log.d("gio", "BleConnect: enabling adapter"); - Intent enableBtIntent = new Intent(adapter.ACTION_REQUEST_ENABLE); - handler.post(new Runnable() { - public void run() { - startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); - } - }); - } else { - Log.d("gio", "BleConnect: adapter is enabled"); - } - if (ctx.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST); - } - installComplete(this); - } - - public boolean enabled() { - return (adapter != null && adapter.isEnabled()); - } - - private final BroadcastReceiver receiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Log.d("gio", "Received broadcast"); - if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - updateState(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)); - } - } - }; - - @Override - public void onDestroy() { - Log.d("gio","onDestroy()"); - stopScan(); - getContext().unregisterReceiver(receiver); - super.onDestroy(); - } - - private final BluetoothAdapter.LeScanCallback scanCallback = new BluetoothAdapter.LeScanCallback() { - public void onLeScan(final BluetoothDevice dev, int rssi, byte[] scanRecord) { - Log.d("gio","onLeScan(): " + dev.getName()); - onScan(dev.getName(), dev.getAddress(), rssi, dev); - } - }; - - public void scan() { - if (!enabled() || getContext().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - Log.d("gio","BleConnect: scan() not enabled or no permissions, wantScan = true"); - wantScan = true; - return; - } - Log.d("gio","BleConnect: scan() starting scan"); - wantScan = false; - handler.post(new Runnable() { - public void run() { - adapter.startLeScan(scanCallback); - } - }); - } - - public void stopScan() { - if (!enabled()) { - return; - } - Log.d("gio", "Stop scan"); - handler.post(new Runnable() { - public void run() { - adapter.stopLeScan(scanCallback); - } - }); - } - - private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() { -@Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - BluetoothDevice device = gatt.getDevice(); - String addr = device.getAddress(); - if (status != BluetoothGatt.GATT_SUCCESS) { - Log.d("gio", "onConnectionStateChange: error code " + status); - onDisconnect(gatt, addr); - Log.d("gio", "gatt.close()"); - gatt.close(); - return; - } - switch (newState) { - case BluetoothProfile.STATE_CONNECTED: { - Log.d("gio", "Connected"); - Log.d("gio", "Address = " + addr); - onConnect(gatt, addr); - break; - } - case BluetoothProfile.STATE_CONNECTING: - case BluetoothProfile.STATE_DISCONNECTING: { - break; - } - case BluetoothProfile.STATE_DISCONNECTED: { - Log.d("gio", "Disconnected"); - onDisconnect(gatt, addr); - Log.d("gio", "gatt.close()"); - gatt.close(); - break; - } - default: { - Log.d("gio", "onConnectionStateChange: unknown state"); - onDisconnect(gatt, addr); - Log.d("gio", "gatt.close()"); - gatt.close(); - break; - } - } - } - public void onServicesDiscovered(BluetoothGatt gatt, int status) { - for (BluetoothGattService serv : gatt.getServices()) { - onDiscoverService(gatt.getDevice().getAddress(), serv.getUuid().toString(), serv); - } - } - public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic chr) { - byte[] v = chr.getValue(); - characteristicChanged(gatt.getDevice().getAddress(), chr.getUuid().toString(), chr, v, v.length); - } - }; - - public void connect(BluetoothDevice dev) { - if (dev == null) { - return; - } - Log.d("gio","BleConnect: connect"); - - handler.post(new Runnable() { - public void run() { - dev.connectGatt(getContext(), false, gattCallback, BluetoothDevice.TRANSPORT_LE); - } - }); - } - - public void disconnect(BluetoothGatt gatt) { - if (gatt == null) { - return; - } - Log.d("gio","BleConnect: disconnect"); - handler.post(new Runnable() { - public void run() { - boolean callClose = false; - BluetoothDevice device = gatt.getDevice(); - if (device != null) { - callClose = (manager.getConnectionState(device, BluetoothProfile.GATT) != BluetoothGatt.STATE_CONNECTED); - } - gatt.disconnect(); - if (callClose) { - gatt.close(); - } - } - }); - } - - public void discoverServices(BluetoothGatt gatt) { - if (gatt == null) { - return; - } - handler.post(new Runnable() { - public void run() { - gatt.discoverServices(); - } - }); - } - - public void discoverCharacteristics(BluetoothGatt gatt, BluetoothGattService serv) { - Log.d("gio","BleConnect: discoverCharacteristics()"); - if (gatt == null) { - Log.d("gio","BleConnect: gatt == null"); - return; - } - List chrs = serv.getCharacteristics(); - if (chrs.isEmpty()) { - Log.d("gio", "BleConnect: no characteristics found!"); - } - for (BluetoothGattCharacteristic chr : chrs) { - Log.d("gio","BleConnect: -- " + chr.getUuid().toString()); - onDiscoverCharacteristic(gatt.getDevice().getAddress(), serv.getUuid().toString(), serv, chr.getUuid().toString(), chr); - } - } - - public void setCharacteristicNotification(BluetoothGatt gatt, BluetoothGattCharacteristic chr) { - gatt.setCharacteristicNotification(chr, true); - - BluetoothGattDescriptor descriptor = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); // Client Characteristic Config - descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); - gatt.writeDescriptor(descriptor); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - Log.d("gio", "BleConnect: onActivityResult()"); - if (requestCode == REQUEST_ENABLE_BT) { - Log.d("gio", "BleConnect: onActivityResult() REQUEST_ENABLE_BT"); - switch (resultCode) { - case Activity.RESULT_OK: { - Log.d("gio", "BleConnect: onActivityResult() -- OK"); - if (wantScan) { - scan(); - } - break; - } - case Activity.RESULT_CANCELED: { - Log.d("gio", "BleConnect: onActivityResult() -- Cancelled"); - break; - } - } - } - } - - @Override - public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults) { - Log.d("gio", "BleConnect: onRequestPermissionsResult"); - if (requestCode == PERMISSION_REQUEST) { - boolean granted = true; - for (int x : grantResults) { - if (x == PackageManager.PERMISSION_DENIED) { - granted = false; - break; - } - } - if (!granted) { - Log.d("gio", "BleConnect: permissions not granted"); - return; - } - Log.d("gio", "BleConnect: permissions granted"); - if (wantScan) { - scan(); - } - } - } - - static private native void installComplete(BleConnect p); - static private native void updateState(int s); - static private native void onScan(String name, String id, int rssi, BluetoothDevice dev); - static private native void onConnect(BluetoothGatt gatt, String id); - static private native void onDisconnect(BluetoothGatt gatt, String id); - static private native void onDiscoverService(String id, String uuid, BluetoothGattService serv); - static private native void onDiscoverCharacteristic(String id, String suuid, BluetoothGattService serv, String cuuid, BluetoothGattCharacteristic chr); - static private native void characteristicChanged(String id, String cuuid, BluetoothGattCharacteristic chr, byte[] value, int length); -} - diff --git a/BlessedConnect.java b/BlessedConnect.java new file mode 100644 index 0000000..bbd1ed6 --- /dev/null +++ b/BlessedConnect.java @@ -0,0 +1,275 @@ +package st.wow.git.ble; + +import java.lang.String; +import java.util.List; +import java.util.UUID; +import android.app.Activity; +import android.app.Fragment; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattService; +import android.bluetooth.BluetoothManager; +import android.bluetooth.le.ScanResult; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.Manifest; +import android.util.Log; + +import com.welie.blessed.BluetoothCentral; +import com.welie.blessed.BluetoothCentralCallback; +import com.welie.blessed.BluetoothPeripheral; +import com.welie.blessed.BluetoothPeripheralCallback; + +public class BlessedConnect extends Fragment { + BluetoothCentral central; + boolean wantScan = false; + + final int PERMISSION_REQUEST = 1; + final int REQUEST_ENABLE_BT = 2; + + public BlessedConnect() { + Log.d("gio", "BlessedConnect()"); + } + + @Override public void onAttach(Context ctx) { + super.onAttach(ctx); + Log.d("gio", "BlessedConnect: onAttach()"); + ctx.registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); + if (ctx.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST); + } + central = new BluetoothCentral(ctx, centralCallback, null); + installComplete(this); + } + + private final BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.d("gio", "Received broadcast"); + if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { + updateState(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)); + } + } + }; + + public boolean enabled() { + Context ctx = getContext(); + //The Blessed library does not expose this functionality, so + //we need to get our own BluetoothAdapter and check its status. + BluetoothAdapter adapter = ((BluetoothManager)ctx.getSystemService(ctx.BLUETOOTH_SERVICE)).getAdapter(); + return (adapter != null && adapter.isEnabled()); + } + + @Override + public void onDestroy() { + Log.d("gio","onDestroy()"); + stopScan(); + getContext().unregisterReceiver(receiver); + super.onDestroy(); + } + + public void scan() { + if (enabled()) { + central.scanForPeripherals(); + } else { + wantScan = true; + } + } + + public void stopScan() { + central.stopScan(); + } + + private final BluetoothCentralCallback centralCallback = new BluetoothCentralCallback() { + @Override + public void onDiscoveredPeripheral(BluetoothPeripheral peripheral, ScanResult scanResult) { + Log.d("gio", "BlessedConnect: onDiscoveredPeripheral(): " + peripheral.getName()); + onScan(peripheral.getName(), peripheral.getAddress(), scanResult.getRssi(), peripheral); + } + + @Override + public void onConnectedPeripheral(BluetoothPeripheral peripheral) { + if (peripheral.getState() == peripheral.STATE_CONNECTED) { + Log.d("gio", "BlessedConnect: Connected to " + peripheral.getName()); + Log.d("gio", "BlessedConnect: Address = " + peripheral.getAddress()); + + onConnect(peripheral, peripheral.getAddress()); + } else { + onDisconnect(peripheral, peripheral.getAddress()); + } + } + + @Override + public void onConnectionFailed(BluetoothPeripheral peripheral, int status) { + Log.d("gio", "BlessedConnect: onConnectionFailed()"); + onDisconnect(peripheral, peripheral.getAddress()); + } + + @Override + public void onDisconnectedPeripheral(BluetoothPeripheral peripheral, int status) { + Log.d("gio", "BlessedConnect: Disconnected"); + onDisconnect(peripheral, peripheral.getAddress()); + } + + @Override + public void onScanFailed(int errorCode) { + Log.d("gio", "BlessedConnect: Scan failed"); + } + + }; + + private final BluetoothPeripheralCallback peripheralCallback = new BluetoothPeripheralCallback() { + public void onBondingFailed(BluetoothPeripheral peripheral) { + Log.d("gio", "BlessedConnect: onBondingFailed()"); + } + public void onBondingStarted(BluetoothPeripheral peripheral) { + Log.d("gio", "BlessedConnect: onBondingStarted()"); + } + public void onBondingSucceeded(BluetoothPeripheral peripheral) { + Log.d("gio", "BlessedConnect: onBondingSucceeded()"); + } + public void onBondLost(BluetoothPeripheral peripheral) { + Log.d("gio", "BlessedConnect: onBondLost()"); + } + public void onCharacteristicUpdate(BluetoothPeripheral peripheral, byte[] value, BluetoothGattCharacteristic characteristic, int status) { + Log.d("gio", "BlessedConnect: onCharacteristicUpdate()"); + characteristicChanged(peripheral.getAddress(), characteristic.getUuid().toString(), characteristic, value, value.length); + } + public void onCharacteristicWrite(BluetoothPeripheral peripheral, byte[] value, android.bluetooth.BluetoothGattCharacteristic characteristic, int status) { + Log.d("gio", "onCharacteristicWrite(): " + characteristic.getUuid().toString()); + } + public void onDescriptorRead(BluetoothPeripheral peripheral, byte[] value, android.bluetooth.BluetoothGattDescriptor descriptor, int status) { + Log.d("gio", "onDescriptorRead()"); + } + public void onDescriptorWrite(BluetoothPeripheral peripheral, byte[] value, android.bluetooth.BluetoothGattDescriptor descriptor, int status) { + Log.d("gio", "onDescriptorWrite(): " + descriptor.getUuid().toString()); + } + public void onMtuChanged(BluetoothPeripheral peripheral, int mtu, int status) { + Log.d("gio", "onMtuChanged()"); + } + public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { + Log.d("gio", "onReadRemoteRssi"); + } + public void onNotificationStateUpdate(BluetoothPeripheral peripheral, BluetoothGattCharacteristic characteristic, int status) { + if (status == BluetoothGatt.GATT_SUCCESS) { + if(peripheral.isNotifying(characteristic)) { + Log.i("gio", String.format("BlessedConnect: Notify set to 'on' for %s", characteristic.getUuid())); + } else { + Log.i("gio", String.format("BlessedConnect: Notify set to 'off' for %s", characteristic.getUuid())); + } + } else { + Log.d("gio", "BlessedConnect: onNotificationStateUpdate(): failed"); + } + } + public void onServicesDiscovered(BluetoothPeripheral peripheral) { + Log.d("gio", "BlessedConnect: onServicesDiscovered()"); + } + }; + + public void connect(BluetoothPeripheral peripheral) { + if (peripheral == null) { + return; + } + Log.d("gio","BlessedConnect: connect"); + central.connectPeripheral(peripheral, peripheralCallback); + } + + public void disconnect(BluetoothPeripheral peripheral) { + if (peripheral == null) { + return; + } + Log.d("gio","BlessedConnect: disconnect"); + peripheral.cancelConnection(); + onDisconnect(peripheral, peripheral.getAddress()); + } + + public void discoverServices(BluetoothPeripheral peripheral) { + if (peripheral == null) { + return; + } + List services = peripheral.getServices(); + for (BluetoothGattService serv : services) { + onDiscoverService(peripheral.getAddress(), serv.getUuid().toString(), serv); + } + } + + public void discoverCharacteristics(BluetoothPeripheral peripheral, BluetoothGattService serv) { + if (peripheral == null || serv == null) { + return; + } + List chrs = serv.getCharacteristics(); + for (BluetoothGattCharacteristic chr : chrs) { + onDiscoverCharacteristic(peripheral.getAddress(), serv.getUuid().toString(), serv, chr.getUuid().toString(), chr); + } + } + + public void readCharacteristic(BluetoothPeripheral peripheral, BluetoothGattCharacteristic chr) { + if (peripheral == null || chr == null) { + return; + } + peripheral.readCharacteristic(chr); + } + public boolean setCharacteristicNotification(BluetoothPeripheral peripheral, BluetoothGattCharacteristic chr) { + if (peripheral == null || chr == null) { + return false; + } + return peripheral.setNotify(chr, true); + } + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d("gio", "BlessedConnect: onActivityResult()"); + if (requestCode == REQUEST_ENABLE_BT) { + Log.d("gio", "BlessedConnect: onActivityResult() REQUEST_ENABLE_BT"); + switch (resultCode) { + case Activity.RESULT_OK: { + Log.d("gio", "BlessedConnect: onActivityResult() -- OK"); + if (wantScan) { + scan(); + } + break; + } + case Activity.RESULT_CANCELED: { + Log.d("gio", "BlessedConnect: onActivityResult() -- Cancelled"); + break; + } + } + } + } + + @Override + public void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults) { + Log.d("gio", "BlessedConnect: onRequestPermissionsResult"); + if (requestCode == PERMISSION_REQUEST) { + boolean granted = true; + for (int x : grantResults) { + if (x == PackageManager.PERMISSION_DENIED) { + granted = false; + break; + } + } + if (!granted) { + Log.d("gio", "BlessedConnect: permissions not granted"); + return; + } + Log.d("gio", "BlessedConnect: permissions granted"); + if (wantScan) { + scan(); + } + } + } + + static private native void installComplete(BlessedConnect p); + + static private native void updateState(int s); + static private native void onScan(String name, String id, int rssi, BluetoothPeripheral peripheral); + static private native void onConnect(BluetoothPeripheral peripheral, String id); + static private native void onDisconnect(BluetoothPeripheral peripheral, String id); + static private native void onDiscoverService(String id, String uuid, BluetoothGattService serv); + static private native void onDiscoverCharacteristic(String id, String suuid, BluetoothGattService serv, String cuuid, BluetoothGattCharacteristic chr); + static private native void characteristicChanged(String id, String cuuid, BluetoothGattCharacteristic chr, byte[] value, int length); +} diff --git a/README.md b/README.md index fc07c55..d42ccc9 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,5 @@ Using Gio, your main event loop will look something like this: } } ``` + +An example heart rate monitor app can be found at [git.wow.st/gmp/hrm](https://git.wow.st/gmp/hrm). diff --git a/ble_android.go b/ble_android.go index 6e52018..8b4b773 100644 --- a/ble_android.go +++ b/ble_android.go @@ -1,5 +1,5 @@ //go:generate mkdir -p classes -//go:generate javac -bootclasspath $ANDROID_HOME/platforms/android-29/android.jar -d classes BleConnect.java +//go:generate javac -bootclasspath $ANDROID_HOME/platforms/android-29/android.jar -classpath blessed-full.jar -d classes BlessedConnect.java //go:generate jar cf Ble.jar -C classes . //go:generate rm -rf classes @@ -24,7 +24,7 @@ import "C" // Types required for ble.go type bleHandle struct { - BleConnect C.jobject + BlessedConnect C.jobject state int } @@ -34,8 +34,7 @@ type Peripheral struct { Name string RSSI int Identifier string - device C.jobject - gatt C.jobject + peripheral C.jobject } type Service struct { @@ -90,17 +89,17 @@ func peripheralLookup(p Peripheral) *BLE { // FIXME: check what happens with "incomplete" Peripherals that have only // an Identifier set. Do the other functions on Peripherals do something // sensible? -func newPeripheral(name, id string, rssi int, dev C.jobject) Peripheral { +func newPeripheral(name, id string, rssi int, peripheral C.jobject) Peripheral { return Peripheral{ Name: name, RSSI: rssi, Identifier: id, - device: dev, + peripheral: peripheral, } } func (p Peripheral) IsIncomplete() bool { - if p.device == 0 { + if p.peripheral == 0 { return true } else { return false @@ -132,7 +131,7 @@ func (b *BLE) readyToScan() bool { connect() var ret bool runInJVM(func(env *C.JNIEnv) { - ret = C.enabled(env, b.handle.BleConnect) == C.JNI_TRUE + ret = C.enabled(env, b.handle.BlessedConnect) == C.JNI_TRUE }) return ret } @@ -141,7 +140,7 @@ func (b *BLE) readyToScan() bool { func (b *BLE) scan() { connect() runInJVM(func(env *C.JNIEnv) { - C.scan(env, b.handle.BleConnect); + C.scan(env, b.handle.BlessedConnect); }) } @@ -149,15 +148,14 @@ func (b *BLE) scan() { func (b *BLE) stopScan() { connect() runInJVM(func(env *C.JNIEnv) { - C.stopScan(env, b.handle.BleConnect); + C.stopScan(env, b.handle.BlessedConnect); }) } //connectPeripheral attempts to connect to a Peripheral func (b *BLE) connectPeripheral(x Peripheral) { - connect() runInJVM(func(env *C.JNIEnv) { - C.connect(env, b.handle.BleConnect, x.device) + C.connect(env, b.handle.BlessedConnect, x.peripheral) }) } @@ -165,7 +163,7 @@ func (b *BLE) connectPeripheral(x Peripheral) { func (b *BLE) cancelConnection(p Peripheral) { connect() runInJVM(func(env *C.JNIEnv) { - C.disconnect(env, b.handle.BleConnect, p.gatt) + C.disconnect(env, b.handle.BlessedConnect, p.peripheral) }) } @@ -178,42 +176,38 @@ func (b *BLE) knownPeripheral(p Peripheral) (Peripheral, bool) { //DiscoverServices asks a Peripheral for its Services func (p Peripheral) DiscoverServices() { - if p.gatt == 0 { - return - } - connect() - log.Printf("discovering services") - runInJVM(func(env *C.JNIEnv) { - C.discoverServices(env, gBLE.handle.BleConnect, p.gatt) - }) + //launch a goroutine because this function calls back directly + //from the same thread (the underlying Java call is synchronous) + go func() { + connect() + log.Printf("discovering services") + runInJVM(func(env *C.JNIEnv) { + C.discoverServices(env, gBLE.handle.BlessedConnect, p.peripheral) + }) + }() } //DiscoverCharacteristics asks a Peripheral for the Characteristics related //to a Service func (p Peripheral) DiscoverCharacteristics(serv Service) { - if p.gatt == 0 { - return - } //launch a goroutine because this function calls back directly - //from the same thread. + //from the same thread (the underlying Java call is synchronous) go func() { connect() log.Printf("discovering characteristics") runInJVM(func(env *C.JNIEnv) { - C.discoverCharacteristics(env, gBLE.handle.BleConnect, p.gatt, serv.service) + C.discoverCharacteristics(env, gBLE.handle.BlessedConnect, p.peripheral, serv.service) }) - log.Printf("discovering characteristics done") }() } //SetNotifyValue subscribes to a characteristic func (p Peripheral) SetNotifyValue(c Characteristic) { - if p.gatt == 0 { - return - } runInJVM(func(env *C.JNIEnv) { - log.Printf("setCharacteristicNotification: %s", c.UUID) - C.setCharacteristicNotification(env, gBLE.handle.BleConnect, p.gatt, c.characteristic) + result := (C.setCharacteristicNotification(env, gBLE.handle.BlessedConnect, p.peripheral, c.characteristic) == C.JNI_TRUE) + if (!result) { + log.Printf("setCharacteristicNotification: %s failed", c.UUID) + } }) } @@ -231,21 +225,21 @@ func NewBLE() *BLE { //Enable func (b *BLE) Enable(w *app.Window) { log.Printf("ble.Enable()") - w.RegisterFragment("st/wow/git/ble/BleConnect") + w.RegisterFragment("st/wow/git/ble/BlessedConnect") } // Go callbacks from Java -//export Java_st_wow_git_ble_BleConnect_installComplete -func Java_st_wow_git_ble_BleConnect_installComplete(env *C.JNIEnv, class C.jclass, b C.jobject) { +//export Java_st_wow_git_ble_BlessedConnect_installComplete +func Java_st_wow_git_ble_BlessedConnect_installComplete(env *C.JNIEnv, class C.jclass, b C.jobject) { log.Printf("installComplete()") if (b == 0) { - log.Printf("BleConnect object is nil!") + log.Printf("BlessedConnect object is nil!") } - gBLE.handle.BleConnect = (C.NewGlobalRef)(env,b) + gBLE.handle.BlessedConnect = (C.NewGlobalRef)(env,b) h := app.PlatformHandle() setJVM(h.JVM) - if C.enabled(env, gBLE.handle.BleConnect) == C.JNI_TRUE { + if C.enabled(env, gBLE.handle.BlessedConnect) == C.JNI_TRUE { gBLE.handle.state = STATE_ON gBLE.ready = true gBLE.events <- UpdateStateEvent{State: gBLE.stringState()} @@ -256,8 +250,8 @@ func Java_st_wow_git_ble_BleConnect_installComplete(env *C.JNIEnv, class C.jclas log.Printf("installComplete() returning") } -//export Java_st_wow_git_ble_BleConnect_updateState -func Java_st_wow_git_ble_BleConnect_updateState(env *C.JNIEnv, class C.jclass, s C.jint) { +//export Java_st_wow_git_ble_BlessedConnect_updateState +func Java_st_wow_git_ble_BlessedConnect_updateState(env *C.JNIEnv, class C.jclass, s C.jint) { log.Printf("UpdateState: %d", s) gBLE.handle.state = (int)(s) if gBLE.handle.state == STATE_ON { @@ -280,13 +274,13 @@ func goOnScan(cname, cid *C.char, rssi C.int, dev C.jobject) { } //export goOnConnect -func goOnConnect(gatt C.jobject, cid *C.char) { +func goOnConnect(p C.jobject, cid *C.char) { id := C.GoString(cid) peripheral := gBLE.retrievePeripheral(id, p) - if peripheral.gatt == 0 { - log.Printf("goOnConnect(): gatt == null") + if peripheral.peripheral == 0 { + log.Printf("goOnConnect(): peripheral == null") } gBLE.connections.UpdateState(peripheral, "connected") @@ -300,8 +294,8 @@ func goOnDisconnect(p C.jobject, cid *C.char) { peripheral := gBLE.retrievePeripheral(id) - if peripheral.device == 0 { - log.Printf("goOnDisconnect(): device == null") + if peripheral.peripheral == 0 { + log.Printf("goOnDisconnect(): peripheral == null") } go func() { @@ -360,8 +354,6 @@ func goOnDiscoverCharacteristic(cid, csuuid *C.char, serv C.jobject, ccuuid *C.c func goOnCharacteristicChanged(cid, ccuuid *C.char, char C.jobject, cvalue *C.char, length C.jint) { id := C.GoString(cid) cuuid := C.GoString(ccuuid) - log.Printf("goOnCharacteristicChanged: %s", cuuid) - log.Printf("goOnCharacteristicChanged: length = %d", length) peripheral := gBLE.retrievePeripheral(id) diff --git a/blessed-full.jar b/blessed-full.jar new file mode 100644 index 0000000000000000000000000000000000000000..e6cd12a53c597a9cb4679160fd8c1d5e9c6c56dc GIT binary patch literal 78587 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

px{;tP!g5Hr!BA3%Er} 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, b); - jmethodID mid = (*env)->GetMethodID(env, cls, "connect", "(Landroid/bluetooth/BluetoothDevice;)V"); + jmethodID mid = (*env)->GetMethodID(env, cls, "connect", "(Lcom/welie/blessed/BluetoothPeripheral;)V"); (*env)->CallObjectMethod(env, b, mid, d); } void disconnect(JNIEnv *env, jobject b, jobject g) { jclass cls = (*env)->GetObjectClass(env, b); - jmethodID mid = (*env)->GetMethodID(env, cls, "disconnect", "(Landroid/bluetooth/BluetoothGatt;)V"); + jmethodID mid = (*env)->GetMethodID(env, cls, "disconnect", "(Lcom/welie/blessed/BluetoothPeripheral;)V"); (*env)->CallVoidMethod(env, b, mid, g); } void discoverServices(JNIEnv *env, jobject b, jobject p) { jclass cls = (*env)->GetObjectClass(env, b); - jmethodID mid = (*env)->GetMethodID(env, cls, "discoverServices", "(Landroid/bluetooth/BluetoothGatt;)V"); + jmethodID mid = (*env)->GetMethodID(env, cls, "discoverServices", "(Lcom/welie/blessed/BluetoothPeripheral;)V"); (*env)->CallVoidMethod(env, b, mid, p); } void discoverCharacteristics(JNIEnv *env, jobject b, jobject g, jobject s) { jclass cls = (*env)->GetObjectClass(env, b); - jmethodID mid = (*env)->GetMethodID(env, cls, "discoverCharacteristics", "(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattService;)V"); + jmethodID mid = (*env)->GetMethodID(env, cls, "discoverCharacteristics", "(Lcom/welie/blessed/BluetoothPeripheral;Landroid/bluetooth/BluetoothGattService;)V"); (*env)->CallVoidMethod(env, b, mid, g, s); } -void +jboolean setCharacteristicNotification(JNIEnv *env, jobject b, jobject g, jobject c) { jclass cls = (*env)->GetObjectClass(env, b); - jmethodID mid = (*env)->GetMethodID(env, cls, "setCharacteristicNotification", "(Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V"); - (*env)->CallVoidMethod(env, b, mid, g, c); + jmethodID mid = (*env)->GetMethodID(env, cls, "setCharacteristicNotification", "(Lcom/welie/blessed/BluetoothPeripheral;Landroid/bluetooth/BluetoothGattCharacteristic;)Z"); + return (*env)->CallBooleanMethod(env, b, mid, g, c); +} + +void +readCharacteristic(JNIEnv *env, jobject b, jobject g, jobject c) { + jclass cls = (*env)->GetObjectClass(env, b); + jmethodID mid = (*env)->GetMethodID(env, cls, "readCharacteristic", "(Lcom/welie/blessed/BluetoothPeripheral;Landroid/bluetooth/BluetoothGattCharacteristic;)V"); + (*env)->CallBooleanMethod(env, b, mid, g, c); } jint @@ -80,7 +87,7 @@ NewGlobalRef(JNIEnv *env, jobject o) { } void -Java_st_wow_git_ble_BleConnect_onScan(JNIEnv *env, jclass class, jstring jname, jstring jid, jint jrssi, jobject dev) { +Java_st_wow_git_ble_BlessedConnect_onScan(JNIEnv *env, jclass class, jstring jname, jstring jid, jint jrssi, jobject dev) { const char* name = (*env)->GetStringUTFChars(env, jname, NULL); const char* id = (*env)->GetStringUTFChars(env, jid, NULL); jobject gdev = (*env)->NewGlobalRef(env, dev); @@ -90,22 +97,23 @@ Java_st_wow_git_ble_BleConnect_onScan(JNIEnv *env, jclass class, jstring jname, } void -Java_st_wow_git_ble_BleConnect_onConnect(JNIEnv *env, jclass class, jobject gatt, jstring jid) { +Java_st_wow_git_ble_BlessedConnect_onConnect(JNIEnv *env, jclass class, jobject peripheral, jstring jid) { const char* id = (*env)->GetStringUTFChars(env, jid, NULL); - jobject ggatt = (*env)->NewGlobalRef(env, gatt); - goOnConnect(ggatt, id); + jobject gperipheral = (*env)->NewGlobalRef(env, peripheral); + goOnConnect(gperipheral, id); (*env)->ReleaseStringUTFChars(env, jid, id); } void -Java_st_wow_git_ble_BleConnect_onDisconnect(JNIEnv *env, jclass class, jobject peripheral, jstring jid) { +Java_st_wow_git_ble_BlessedConnect_onDisconnect(JNIEnv *env, jclass class, jobject peripheral, jstring jid) { const char* id = (*env)->GetStringUTFChars(env, jid, NULL); jobject gperipheral = (*env)->NewGlobalRef(env, peripheral); goOnDisconnect(gperipheral, id); (*env)->ReleaseStringUTFChars(env, jid, id); } -Java_st_wow_git_ble_BleConnect_onDiscoverService(JNIEnv *env, jclass class, jstring jid, jstring juuid, jobject serv) { +void +Java_st_wow_git_ble_BlessedConnect_onDiscoverService(JNIEnv *env, jclass class, jstring jid, jstring juuid, jobject serv) { const char* id = (*env)->GetStringUTFChars(env, jid, NULL); const char* uuid = (*env)->GetStringUTFChars(env, juuid, NULL); jobject gserv = (*env)->NewGlobalRef(env, serv); @@ -115,7 +123,7 @@ Java_st_wow_git_ble_BleConnect_onDiscoverService(JNIEnv *env, jclass class, jstr } void -Java_st_wow_git_ble_BleConnect_onDiscoverCharacteristic(JNIEnv *env, jclass class, jstring jid, jstring jsuuid, jobject serv, jstring jcuuid, jobject chr) { +Java_st_wow_git_ble_BlessedConnect_onDiscoverCharacteristic(JNIEnv *env, jclass class, jstring jid, jstring jsuuid, jobject serv, jstring jcuuid, jobject chr) { const char* id = (*env)->GetStringUTFChars(env, jid, NULL); const char* suuid = (*env)->GetStringUTFChars(env, jsuuid, NULL); const char* cuuid = (*env)->GetStringUTFChars(env, jcuuid, NULL); @@ -128,7 +136,7 @@ Java_st_wow_git_ble_BleConnect_onDiscoverCharacteristic(JNIEnv *env, jclass clas } void -Java_st_wow_git_ble_BleConnect_characteristicChanged(JNIEnv *env, jclass class, jstring jid, jstring jcuuid, jobject chr, jbyteArray jvalue, jint len) { +Java_st_wow_git_ble_BlessedConnect_characteristicChanged(JNIEnv *env, jclass class, jstring jid, jstring jcuuid, jobject chr, jbyteArray jvalue, jint len) { const char* id = (*env)->GetStringUTFChars(env, jid, NULL); const char* cuuid = (*env)->GetStringUTFChars(env, jcuuid, NULL); jbyte* value = (*env)->GetByteArrayElements(env, jvalue, NULL); diff --git a/jni_android.h b/jni_android.h index da4f0ea..d8977ec 100644 --- a/jni_android.h +++ b/jni_android.h @@ -7,7 +7,8 @@ void connect(JNIEnv *env, jobject b, jobject d); void disconnect(JNIEnv *env, jobject b, jobject g); void discoverServices(JNIEnv *env, jobject b, jobject p); void discoverCharacteristics(JNIEnv *env, jobject b, jobject g, jobject s); -void setCharacteristicNotification(JNIEnv *env, jobject b, jobject g, jobject c); +void readCharacteristic(JNIEnv *env, jobject b, jobject g, jobject c); +jboolean setCharacteristicNotification(JNIEnv *env, jobject b, jobject g, jobject c); jint GetEnv(JavaVM *vm, JNIEnv **env, jint version); jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args); jint DetachCurrentThread(JavaVM *vm); diff --git a/timber.jar b/timber.jar new file mode 100644 index 0000000000000000000000000000000000000000..7cf3aeb79aaebd8c535621aacb64378b1daddca0 GIT binary patch literal 8434 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 KB$51e_x}JQm#KgN literal 0 HcmV?d00001