From 17190d8770789a3989a4481b367e728768c1270d Mon Sep 17 00:00:00 2001 From: Rashiq Ahmad Date: Wed, 25 Dec 2013 20:01:52 +0100 Subject: [PATCH] Backported the Android app to API 9. See Bug #783 for more details. --- AndroidManifest.xml | 5 +- assets/{ => fonts}/DejaVuSansCondensed.ttf | Bin assets/{ => fonts}/Parabaik.ttf | Bin build.gradle | 7 +- project.properties | 14 - res/drawable-hdpi/ic_find_next_holo_dark.png | Bin 0 -> 1047 bytes .../ic_find_previous_holo_dark.png | Bin 0 -> 1039 bytes res/drawable-mdpi/ic_find_next_holo_dark.png | Bin 0 -> 740 bytes .../ic_find_previous_holo_dark.png | Bin 0 -> 744 bytes res/drawable-xhdpi/ic_find_next_holo_dark.png | Bin 0 -> 1458 bytes .../ic_find_previous_holo_dark.png | Bin 0 -> 1432 bytes res/layout/main.xml | 2 +- res/layout/simple_list_item.xml | 11 + res/layout/webview_find.xml | 33 ++ res/menu/fileselector.xml | 5 +- res/menu/main.xml | 27 +- res/menu/webview_menu.xml | 28 ++ res/values/strings.xml | 2 + settings.gradle | 1 + .../BackwardsCompatibilityTools.java | 37 ++ .../CompatFindActionModeCallback.java | 209 +++++++++ .../kiwixmobile/KiwixMobileActivity.java | 231 ++++++---- .../kiwixmobile/KiwixMobileFragment.java | 62 +-- src/org/kiwix/kiwixmobile/KiwixSettings.java | 130 ------ .../kiwixmobile/KiwixSettingsActivity.java | 117 +++++ src/org/kiwix/kiwixmobile/KiwixWebView.java | 50 ++- src/org/kiwix/kiwixmobile/LanguageUtils.java | 17 +- .../kiwix/kiwixmobile/ZimContentProvider.java | 410 +++++++++--------- .../kiwixmobile/ZimFileSelectActivity.java | 40 +- 29 files changed, 937 insertions(+), 501 deletions(-) rename assets/{ => fonts}/DejaVuSansCondensed.ttf (100%) rename assets/{ => fonts}/Parabaik.ttf (100%) delete mode 100644 project.properties create mode 100644 res/drawable-hdpi/ic_find_next_holo_dark.png create mode 100644 res/drawable-hdpi/ic_find_previous_holo_dark.png create mode 100644 res/drawable-mdpi/ic_find_next_holo_dark.png create mode 100644 res/drawable-mdpi/ic_find_previous_holo_dark.png create mode 100644 res/drawable-xhdpi/ic_find_next_holo_dark.png create mode 100644 res/drawable-xhdpi/ic_find_previous_holo_dark.png create mode 100644 res/layout/simple_list_item.xml create mode 100644 res/layout/webview_find.xml create mode 100644 res/menu/webview_menu.xml create mode 100644 settings.gradle create mode 100644 src/org/kiwix/kiwixmobile/BackwardsCompatibilityTools.java create mode 100644 src/org/kiwix/kiwixmobile/CompatFindActionModeCallback.java delete mode 100644 src/org/kiwix/kiwixmobile/KiwixSettings.java create mode 100644 src/org/kiwix/kiwixmobile/KiwixSettingsActivity.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a18dfd556..913096658 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -15,10 +15,11 @@ - + 1{qLkI3$xp;d+WCBm8 z!U>lAGhF(+3KMiVT$lxQ!UerncTeJ4WWLa~FrlTn=kv|NnpbdF8zOpPx1=xps;Clz(vcTj3P0eS7&l8#vuKKRuA1TLQ=I)rkXEVbT@u1la-QVV{-u3sovzL}qeBx5Q zz1wO<#Wq%capw*%t2z8b+zY59L+{S+?oAV>%X><05R@ps!ClTbKfp`z=c}Om4#ubN zmu;G-s1G>>e?TzwIN$7jV#=4lTJPC3rn|~cduoa@b1WKub+P9 z=24k}hJ}P_h$*znPEC}au;46Q%Fejk%kHqqQ)|+M5-`7?6H+ycwn#+L~ z?=RW0>#6pVD<`advki7`S$w2E=~YkF)6?Nek7oP7JO1Rsx}$mqu?IJ}N4{Sd;}ZDu z(^RSdf6i7ne!8;xRbYS3Pp|&kk_y?pbz0{=_vseuS;QPqo-Et-ynJ@<|E$;Ne@_hw z-)BDk{;kbY(&j66%l$Qx=K5S$|Jh~sq)(zjI^uy_3iN>yyL7v3(PB1U?~BYPB3ac1 zZ?8`F(p)k@iR*ND|04T0Pp|RYF#evtihTv6p5(WRtMa;Dnrk-H94(p~>mMYf{bkuF zH?anH#+!!6KQ&ID65vvM^V>FE3rmiIv(cMFq8itz+U9xMExz$%`TF(ezdvh~4*x${ z(@IwLVD8%2M`kqt&RZuJrreabG`mdczueuDcZ@0bnZN#T+vhP+$@SmqKdfhh7Abg% z%~t?sB-Ikvh?11Vl2ohYqEsNoU}RuusB37TYiJQ-XkukxXk}ocYhZ3=VDQn*TL(o$ zZhlH;S|x4`4cVV305wR0YzWRzD=AMbN@Z|N$xljE@XSq2PYp^I`grbhu^P_sbynGh1 z7^-S1RXq^?zMy8x45{u`SB0Bj99^p~$#cJ1AGYM!lJ|Fa-p#vx_sofm2U*V&WKxecpmK>Iw{6>tgSBOgLP2E%t|l zXRByfh+t)@R@p08r{#Ay99)-u^*VFWj_*>(_%#*RZ`f57cvNI+cu42w^$}P3rW-{> z9(kl!F2S^5YF)Za?T?qX2csofwbahl{=Ib5>{)=@w2iH^+sgj$Q#i6Bd-=mx`(hhD zFgATWyR#$d(I9me>Ua z#l;zxez9||ba!A|1C#CF-dGd1hwDl1FovAE+%5L%R=x^SijMw}-YZ(RDna}(z?S9ni>d{lXqxRz!G2be7bH(OY ztzk<=49ayb-TCsy({bIzb(*Yv3O(wZ@4npicjMht1$#He=G2bv42hVuPL=x(_X~h$Q{c6UiyY(YWL)W&aT_n zE!-fs_VlIs$IKh<*v0A1YUE(McJ0dD54$)sQmx*({YhlGb~Zll=h9Bz%V`CDh2A#~ zd}(Bz#`O44s!@df<|&C$X=~UunDsXNT2%y0uYr&1kJ@uL&Xj08sqq+?fmBOeBT7;d zOH!?pi&B9UgOP!up{}8UuAxPUp^24&p_PG&u7SCgfx$;JZygj3x%nxXX_dG&G-Q9C y0MsA}vLQG>t)x7$D3!r6B|j-u!8128JvAsbF{QHbWU38N5re0zpUXO@geCxB!_@2m literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_find_next_holo_dark.png b/res/drawable-mdpi/ic_find_next_holo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..c138916f9c4552ef27c0c54f78d0e003bdbf4785 GIT binary patch literal 740 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(ernVDxlx4DmSrc5-Y6Z-K#1Te!q^-L+XF!A8R3lSM9O z#CYsf^43(3U;3<1QaoBJbJ~nWk$&yP=g!^yc}v42D7u-yFH2Yvs+49r8-x}Kf z>^|yLcFV~1&bF;GC$evD$UMi#x2#)^#d3ajaO^`a#qjicCN74GG>5$Vnn$g)Th-bmln-%dTjT88vpSr z6XNeOPv53{$7?yW#`$Z<)cQ8{#Fh6KvpRqE(wM-dxn{v5d4D7Rc@hT})qj~O#PDZb z$0gRka$ip@Ptf{PHGjfglVyi%804fUT&|9>eS9zcsnffz%&33&ugvy2@~y(V<<3N% z?-NB8XZffdDUWt9O8cg1y|Iqj!Y25)&VR}M4E9Gk=WY)+4g;nN)e_f;l9a@fRIB8o zR3OD*WMF8hYiOWrXc1y)Vr5`xWniLfU~Xk#@X^d$2Sr0}eoAIqC2kE3*`Fr>HAsSN t2+mI{DNig)WpGT%PfAtr%uP&B4N6T+sVqF1Y6Dcn;OXk;vd$@?2>{EXF{S_j literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/ic_find_previous_holo_dark.png b/res/drawable-mdpi/ic_find_previous_holo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d2392744c67857a607f8dc231b2251ee205991de GIT binary patch literal 744 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(ernVD)ry4DmSrc9N%uNPUUFXqQZ zdMoFPa_!VM({;6DsGENL*G>7=B2)bvE7D8$Pq-Sf$mQ0Ph0_ekm&Kl{vTzScJBSK(Yci=0}PYxObjnCHxOa{asWSD)To&S`DYGbba$^izOi zY2S96yBaC1^*IT4UC-)Qgt*kX{_;C_vPJBB@^%}$oebBD*z>j59B_%=(ZXY4?)t#x zw%pehz6ZlaXRP>Jxy6W~>7B;X&un_yYaT>oU%kY5tls`rB+JY9+Kw=Yn%X8O-xS>N=;0uEIgTN160J|>FVdQ&MBb@0Js7y-~a#s literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_find_next_holo_dark.png b/res/drawable-xhdpi/ic_find_next_holo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e822605379b231ebc9919da49f73905947a1c7b5 GIT binary patch literal 1458 zcmZ`(c{tPw82-gz+_^feGn6pQNXR&57|k%wY07;J29uebF_Jr_#u-x9k=*N8<(e$x zh)|epjy8-O71pfE#3JmpyZ`JT`##V6zR&kO-}}7J^ZoJNcCbT>3dsrq03d3GLE*TL z_)aj0tAO{@i(KXL!J<*X!L7{UF76~4f^iAwI_7Vl9||%B01(p(g~SK4*!e+ZX`=Ma zk_VlmWNc}Q&uIwW)m59%Roxa@fdEPPUPcHmD{|1v1xl$r^O8YW`Yn*{4Ulvhh=(8Q z2&O_@TYj02oMyM8%y}jGaw()J|`g$}oiWST#IwbWka^N_j zggsLY5q5hs_%P#1Le7l#?Ttfeuk+XYa&d^hGdvxs@8UuI2$fDIl>iy=#YQ33AfEgj67hEXGk9WNYi6OnV>9Po& z(5%ID(5^}zd1o~sIn7dj>GXRUDPvL`eg<7--RGSIm-aa-Lho>q?UO1p&-;^EKe(P= zJM_hPM?OLdP=6J=2UX*wk7FyS{hE2WquN`h7F*eo77~VuM2(&D@{J0dj_2o8C*y_e zZm)Gl)*Vlui52t&r9Ckrt3txfOcQsSA-0Q{{#cTMv~LwXHSz`&MinSYqA7HZN|oSg zZXF9UZF=r|e(xPP{hNPuKmJi~Wf(CI@~|~D>9SbNwkDCcsaX9TYdEKJ*qh%^B~=%r z(m?R1*BsA5*UUw%YA-`Kli*bfsP0hr`pJ z2jLvDUJF!v;M6+X*rrhf-?(IMPgB6p0YdV0G5bKc)_z9yYOhSo>yY#*(BMizEZpeA z8;WH~c39|$?TWs;vjL2cl5;gR=l&{bzNCEfW_bLkcT~=8+3wuk#{z>3Y8e`Vs^3~2 zR?9W6F=l_I5~p7v1N%w}H79Tz%qGd1&a*$nmdY=z#4~qZbh;h00dnO=0w@K=`T}rD zHRAsLR$o>NuTV@ECJU;;vpj;fo(wkZY^v9ihBhO4MG^XO-cKS27qsQJD`lA%wGbe* zYPAtqSsmpNT0Cd)sZ)4lI@#-dM#yTBF^L0!7 zZj>sB*>c!w@kURoC`%kY)R&~wTzvoQ$iHY{OeWq^vU> z1F`aK&3&S7b%hJN_VwbDT+KaM61{`X)^aDdHZV-03iLqA_A1YJ-RTPp1xbD!T##v| zX&ryV+?D7^AC_WXUfPB66Upl|@wDsLfQ>rCMq%jM{M$C)#O0~p@q=Dg-#=K2e>NAV zgN)8iPYUAxIJF2%=LkPS1kuPhjL0=W7Yc(xU{DCm5D(Kcg2IfTdJw3A5fu7aAFK7B z043Ou{t;1xFd~5T3-%!@Sy2c9L>!Ue7acl8H0CY=R+e_C J26OMEzW`00lnnp? literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_find_previous_holo_dark.png b/res/drawable-xhdpi/ic_find_previous_holo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba45876c6be33284fb681deeb4fb8c7c3a7d098 GIT binary patch literal 1432 zcmZ{kdpHvc7{+HvWN9o?j#hH3$>x%o`^;r%>{9N=m`g}D5t2n=B=?CpQG`y0B9zO7 zkZVP`!0RW*IEXIW7JF&#_3m~0?Fq${L zo8Kh^S%mHh=|qsVHP$3EodKPSxnapU2odmX>pUqSl$c<3f&z>?B!Gn+P|(AWfR=ii z#f##S3Jwnni_)JAvNh>H-*~`Gyqt=ouTHMem%}FNKaWSYaQ;<6uP+0zYPa1Te?S7J z<=J|YGqo|4A`Bg~8jO#P3~84iyjSG2%_V|wOo!h8m?DBBRrF%fyS zv2LGwr>v?pxtFC_hO~Dwua0k0Rwq81{q*~5og$K0yQ1(+;BcezzM7u*E>o^l74jW? zzY=*IY8ag4tUm+J&eZ;G`=VAKIF!K)v&c7>f%eCYrnHJC{Qs*28K+Z;o+ zAKTki?qHt;`{J=5DD`Fgo2%eaR|*#kQi3Khp#|W!TRUSNo7Zyf$d1uSg74)gua)c7IMZCTnmjEn9QQG$ zucV_@%UuQvGafFiZ*eS-^gVcRIK?Wb4y~BE2PbX&QupmK4(AzH2DqAcutxjEjx{e% zIt+^+Sevz>NXo^e-V}8RY~_s<#JSGwyWFB^MsPqR4MP-jQ{P5Jtqo}m#i6uEcat-3 zjyca6EngG*3|Hg~*oB;4gdt^0TqXza+sdm}xLEnfDX)Xq{qqe4O{$yrQ=*81!UVaC z<+WT+8n{&V4CD0lcT!wc-;IU*?~xN{GiVzNKV--8{%W2p`b*J>ge-_Zl559HgmmXz zT8paD`?_q}TN^60F_HN$zAQn$BB2?no;S+^>N?j((f6F}7ZZJa8xthLS|~*@v+c3< zS6-558=vvYmP@t0MGVmDg{&e0bhHS*iQ58Hy~wluGL{u<^+Y^jy|>a-;YZDc_FX5f zr*^L&v8c)g*EG&rj4K5}0J@2##Mz%6Mfxsizo|MOU~tZPCPv-8562!?`W&-0%{+}V zx{J(nTe_5#-<*Zfa%Y2Td@N_}X99V)ko-eIRb7)G^=swY-Q-(I(e-yCmR^OE?O7lE zEq3>8DY&u-TN1)97)B$=KUXPy(uuUFlnVtsjH9#3)d|b_bMnIpQ^C>Oitmx>-&H74bkUc(AQ6O& zca}{H;zKU(!Y6Ky3$+F(jxV*fX=VCnHRQ+%6=o-^P-u@grN*DHGZ~dbur_!RD54I5 zn9L1btPV_`OAD^XOQim(P6LVmqaCB4q7+99<5N7!Q~oDY3^8*E@$v|vqC9C-J^&hU z1VRk~S3@942rU#Gfr4wP!F5n@IPZ)#>_3ITATK}f@c%C`{MSVVIDLp iz{D$vLWN=jJ$$GHs)tv2a2HjdzXZUV;V^8pd(2;tmxtm2 literal 0 HcmV?d00001 diff --git a/res/layout/main.xml b/res/layout/main.xml index bf4fb4d29..c951ce2fc 100644 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -28,7 +28,7 @@ android:inputType="text|textCapWords" android:maxLines="1" android:background="@android:color/background_dark" - android:textColor="@android:color/primary_text_dark"/> + android:textColor="@android:color/white"/> diff --git a/res/layout/simple_list_item.xml b/res/layout/simple_list_item.xml new file mode 100644 index 000000000..050f1ab11 --- /dev/null +++ b/res/layout/simple_list_item.xml @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/res/layout/webview_find.xml b/res/layout/webview_find.xml new file mode 100644 index 000000000..d5fd8643f --- /dev/null +++ b/res/layout/webview_find.xml @@ -0,0 +1,33 @@ + + + + + + + + diff --git a/res/menu/fileselector.xml b/res/menu/fileselector.xml index 14edd4f71..05a26b85d 100644 --- a/res/menu/fileselector.xml +++ b/res/menu/fileselector.xml @@ -1,11 +1,12 @@ - + + app:showAsAction="always"/> \ No newline at end of file diff --git a/res/menu/main.xml b/res/menu/main.xml index eb1cfad0e..a125bacad 100644 --- a/res/menu/main.xml +++ b/res/menu/main.xml @@ -1,81 +1,82 @@ - + + app:showAsAction="ifRoom"/> + app:showAsAction="ifRoom"/> + app:showAsAction="ifRoom"/> + app:showAsAction="ifRoom"/> + app:showAsAction="ifRoom"/> + app:showAsAction="ifRoom"/> + app:showAsAction="ifRoom"/> + app:showAsAction="never"/> + app:showAsAction="never"/> + app:showAsAction="never"/> + app:showAsAction="ifRoom"/> + app:showAsAction="never"/> diff --git a/res/menu/webview_menu.xml b/res/menu/webview_menu.xml new file mode 100644 index 000000000..0d9c3c7cb --- /dev/null +++ b/res/menu/webview_menu.xml @@ -0,0 +1,28 @@ + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 0adbc1904..e30467886 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -54,4 +54,6 @@ Share via Language Choose a language + Delete Tab + Do you want to delete this tab? diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..0268643af --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':android' \ No newline at end of file diff --git a/src/org/kiwix/kiwixmobile/BackwardsCompatibilityTools.java b/src/org/kiwix/kiwixmobile/BackwardsCompatibilityTools.java new file mode 100644 index 000000000..50a7de603 --- /dev/null +++ b/src/org/kiwix/kiwixmobile/BackwardsCompatibilityTools.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013 Rashiq Ahmad + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +package org.kiwix.kiwixmobile; + + +import android.os.Build; + +public class BackwardsCompatibilityTools { + + public static final boolean newApi() { + + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + } + + public static final boolean equalsOrNewThanApi(int api) { + + return Build.VERSION.SDK_INT >= api; + } + +} diff --git a/src/org/kiwix/kiwixmobile/CompatFindActionModeCallback.java b/src/org/kiwix/kiwixmobile/CompatFindActionModeCallback.java new file mode 100644 index 000000000..d9614ab74 --- /dev/null +++ b/src/org/kiwix/kiwixmobile/CompatFindActionModeCallback.java @@ -0,0 +1,209 @@ +/* + * Copyright 2013 Rashiq Ahmad + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +package org.kiwix.kiwixmobile; + +import android.content.Context; +import android.support.v7.view.ActionMode; +import android.text.Editable; +import android.text.Selection; +import android.text.Spannable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.webkit.WebView; +import android.widget.EditText; + +import java.lang.reflect.Method; + +public class CompatFindActionModeCallback implements ActionMode.Callback, TextWatcher, View.OnClickListener { + + public boolean mIsActive; + + private View mCustomView; + + private EditText mEditText; + + private WebView mWebView; + + private InputMethodManager mInput; + + private boolean mMatchesFound; + + private ActionMode mActionMode; + + public CompatFindActionModeCallback(Context context) { + mCustomView = LayoutInflater.from(context).inflate(R.layout.webview_find, null); + mEditText = (EditText) mCustomView.findViewById(R.id.edit); + mEditText.setOnClickListener(this); + mInput = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + mIsActive = false; + setText(""); + } + + public void setActive() { + mIsActive = true; + } + + public void finish() { + mActionMode.finish(); + mWebView.clearMatches(); + } + + // Place text in the text field so it can be searched for. Need to press + // the find next or find previous button to find all of the matches. + public void setText(String text) { + mEditText.setText(text); + Spannable span = mEditText.getText(); + int length = span.length(); + + // Ideally, we would like to set the selection to the whole field, + // but this brings up the Text selection CAB, which dismisses this + // one. + Selection.setSelection(span, length, length); + + // Necessary each time we set the text, so that this will watch + // changes to it. + span.setSpan(this, 0, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + mMatchesFound = false; + } + + // Set the WebView to search. Must be non null, and set before calling startActionMode. + public void setWebView(WebView webView) { + if (null == webView) { + throw new AssertionError("WebView supplied to CompatFindActionModeCallback cannot be null"); + } + mWebView = webView; + } + + // Move the highlight to the next match. + // If true, find the next match further down in the document. + // If false, find the previous match, up in the document. + private void findNext(boolean next) { + + if (mWebView == null) { + throw new AssertionError("No WebView for CompatFindActionModeCallback::findNext"); + } + + mWebView.findNext(next); + } + + // Highlight all the instances of the string from mEditText in mWebView. + public void findAll() { + if (mWebView == null) { + throw new AssertionError("No WebView for CompatFindActionModeCallback::findAll"); + } + CharSequence find = mEditText.getText(); + if (find.length() == 0) { + mWebView.clearMatches(); + mMatchesFound = false; + mWebView.findAll(null); + } else { + mMatchesFound = true; + mWebView.findAll(find.toString()); + + // Enable word highlighting with reflection + try { + for (Method ms : WebView.class.getDeclaredMethods()) { + if (ms.getName().equals("setFindIsUp")) { + ms.setAccessible(true); + ms.invoke(mWebView, true); + break; + } + } + } catch (Exception ignored) { + + } + } + } + + // Show on screen keyboard + public void showSoftInput() { + mInput.showSoftInput(mEditText, 0); + } + + @Override + public void onClick(View v) { + findNext(true); + } + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mode.setCustomView(mCustomView); + mode.getMenuInflater().inflate(R.menu.webview_menu, menu); + mActionMode = mode; + Editable edit = mEditText.getText(); + Selection.setSelection(edit, edit.length()); + mMatchesFound = false; + mEditText.requestFocus(); + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + mActionMode = null; + mIsActive = false; + mWebView.clearMatches(); + mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0); + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + if (mWebView == null) { + throw new AssertionError("No WebView for CompatFindActionModeCallback::onActionItemClicked"); + } + + mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0); + + switch (item.getItemId()) { + case R.id.find_prev: + findNext(false); + break; + case R.id.find_next: + findNext(true); + break; + default: + return false; + } + return true; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // Does nothing. Needed to implement TextWatcher. + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + findAll(); + } + + @Override + public void afterTextChanged(Editable s) { + // Does nothing. Needed to implement TextWatcher. + } +} \ No newline at end of file diff --git a/src/org/kiwix/kiwixmobile/KiwixMobileActivity.java b/src/org/kiwix/kiwixmobile/KiwixMobileActivity.java index fd33fdd96..1991f64e3 100644 --- a/src/org/kiwix/kiwixmobile/KiwixMobileActivity.java +++ b/src/org/kiwix/kiwixmobile/KiwixMobileActivity.java @@ -19,20 +19,23 @@ package org.kiwix.kiwixmobile; -import android.app.ActionBar; -import android.app.FragmentTransaction; + +import android.annotation.TargetApi; +import android.app.AlertDialog; import android.content.ClipData; -import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; +import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; @@ -44,15 +47,18 @@ import android.view.ViewGroup; import android.view.ViewParent; import android.view.Window; import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.Spinner; import java.util.ArrayList; -public class KiwixMobileActivity extends FragmentActivity implements ActionBar.TabListener, - View.OnLongClickListener, View.OnDragListener, KiwixMobileFragment.FragmentCommunicator { +import static org.kiwix.kiwixmobile.BackwardsCompatibilityTools.equalsOrNewThanApi; +import static org.kiwix.kiwixmobile.BackwardsCompatibilityTools.newApi; + + +public class KiwixMobileActivity extends ActionBarActivity implements ActionBar.TabListener, + View.OnLongClickListener, KiwixMobileFragment.FragmentCommunicator { public static ArrayList mPrefState; @@ -66,6 +72,8 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T private KiwixMobileFragment mCurrentFragment; + private View.OnDragListener mOnDragListener; + private int mNumberOfTabs = 0; private int mCurrentDraggedTab; @@ -74,29 +82,38 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T private int mTabsHeight; + private CompatFindActionModeCallback mCompatCallback; + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_PROGRESS); + setProgressBarVisibility(true); handleLocaleCheck(); setContentView(R.layout.viewpager); - // Set an OnDragListener on the entire View. Now we can track, if the user drags the - // Tab outside the View - getWindow().getDecorView().setOnDragListener(this); + // Set an OnDragListener on the entire View. Now we can track, + // if the user drags the Tab outside the View + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + setUpOnDragListener(); + getWindow().getDecorView().setOnDragListener(mOnDragListener); + } mViewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager()); mViewPager = (ViewPager) findViewById(R.id.viewPager); - mActionBar = getActionBar(); + mActionBar = getSupportActionBar(); mPrefState = new ArrayList(); + mCompatCallback = new CompatFindActionModeCallback(this); + mIsFullscreenOpened = false; setUpViewPagerAndActionBar(); @@ -107,7 +124,7 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T private void setUpViewPagerAndActionBar() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + if (equalsOrNewThanApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)) { mActionBar.setHomeButtonEnabled(false); } @@ -154,6 +171,73 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T }); } + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void setUpOnDragListener() { + mOnDragListener = new View.OnDragListener() { + + // Delete the current Tab, that is being dragged, if it hits the bounds of the Screen + @Override + public boolean onDrag(View v, DragEvent event) { + + DisplayMetrics displaymetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); + + // Get the height of the title bar + final int titleBarHeight; + + switch (displaymetrics.densityDpi) { + + case DisplayMetrics.DENSITY_HIGH: + titleBarHeight = 48; + break; + + case DisplayMetrics.DENSITY_MEDIUM: + titleBarHeight = 32; + break; + + case DisplayMetrics.DENSITY_LOW: + titleBarHeight = 24; + break; + + default: + titleBarHeight = 0; + } + + // Get the width and height of the screen + final int screenHeight = displaymetrics.heightPixels; + final int screenWidth = displaymetrics.widthPixels; + + // Get the current position of the View, that is being dragged + final int positionX = (int) event.getX(); + final int positionY = (int) event.getY(); + + if (event.getAction() == DragEvent.ACTION_DRAG_EXITED) { + + removeTabAt(mCurrentDraggedTab); + return true; + } + + if (event.getAction() == DragEvent.ACTION_DROP) { + + // Does it hit the boundries on the x-axis? + if ((positionX > screenWidth - (0.25 * mTabsWidth)) || + (positionX < (0.25 * mTabsWidth))) { + Log.i("kiwix", "Dragged out"); + removeTabAt(mCurrentDraggedTab); + } + // Does it hit the boundries on the y-axis? + else if ((positionY > screenHeight - (0.25 * mTabsHeight)) || + ((positionY - titleBarHeight) < (0.5 * mTabsHeight))) { + Log.i("kiwix", "Dragged out"); + removeTabAt(mCurrentDraggedTab); + } + return true; + } + return false; + } + }; + } + // Reset the Locale and change the font of all TextViews and its subclasses, if necessary private void handleLocaleCheck() { LanguageUtils.handleLocaleChange(this); @@ -176,13 +260,10 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T mCurrentFragment = getCurrentVisibleFragment(); - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - switch (item.getItemId()) { case R.id.menu_home: case android.R.id.home: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); mCurrentFragment.openMainPage(); break; @@ -195,18 +276,18 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T break; case R.id.menu_searchintext: - mCurrentFragment.webView.showFindDialog("", true); - break; + mCompatCallback.setActive(); + mCompatCallback.setWebView(mCurrentFragment.webView); + mCompatCallback.showSoftInput(); + startSupportActionMode(mCompatCallback); case R.id.menu_forward: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); if (mCurrentFragment.webView.canGoForward()) { mCurrentFragment.webView.goForward(); } break; case R.id.menu_back: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); if (mCurrentFragment.webView.canGoBack()) { mCurrentFragment.menu.findItem(R.id.menu_forward).setVisible(true); mCurrentFragment.webView.goBack(); @@ -214,7 +295,6 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T break; case R.id.menu_randomarticle: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); mCurrentFragment.openRandomArticle(); break; @@ -223,22 +303,18 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T break; case R.id.menu_help: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); mCurrentFragment.showWelcome(); break; case R.id.menu_openfile: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); mCurrentFragment.selectZimFile(); break; case R.id.menu_exit: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); finish(); break; case R.id.menu_settings: - imm.hideSoftInputFromWindow(mCurrentFragment.articleSearchtextView.getWindowToken(), 0); // Display the fragment as the main content. mCurrentFragment.selectSettings(); break; @@ -270,7 +346,7 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T private void openFullScreen() { mCurrentFragment = getCurrentVisibleFragment(); - getActionBar().hide(); + getSupportActionBar().hide(); mCurrentFragment.exitFullscreenButton.setVisibility(View.VISIBLE); mCurrentFragment.menu.findItem(R.id.menu_fullscreen) .setTitle(getResources().getString(R.string.menu_exitfullscreen)); @@ -284,7 +360,7 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T private void closeFullScreen() { mCurrentFragment = getCurrentVisibleFragment(); - getActionBar().show(); + getSupportActionBar().show(); mCurrentFragment.menu.findItem(R.id.menu_fullscreen) .setTitle(getResources().getString(R.string.menu_fullscreen)); mCurrentFragment.exitFullscreenButton.setVisibility(View.INVISIBLE); @@ -298,13 +374,22 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { - mCurrentFragment = getCurrentVisibleFragment(); + + // Finish the search functionality on API 11< + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (mCompatCallback.mIsActive) { + mCompatCallback.finish(); + return true; + } + } // handle the back button for the WebView in the current Fragment + mCurrentFragment = getCurrentVisibleFragment(); mCurrentFragment.onKeyDown(keyCode, event); return true; } + return super.onKeyDown(keyCode, event); } @@ -332,7 +417,7 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T // current tab would throw a NullPointerException, if the app were in landscape mode and // therefore possibly in NAVIGATION_MODE_LIST mode if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) { - getActionBar().getSelectedTab().setText(title); + getSupportActionBar().getSelectedTab().setText(title); } if (mPrefState.size() != 0) { if (mPrefState.get(position).hasToBeRefreshed()) { @@ -482,14 +567,14 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T mCurrentFragment = getCurrentVisibleFragment(); String title = getResources().getString(R.string.app_name); - if (mCurrentFragment.webView.getTitle() != null && - !mCurrentFragment.webView.getTitle().isEmpty()) { + if (mCurrentFragment.webView.getTitle() != null + && !mCurrentFragment.webView.getTitle().isEmpty()) { title = mCurrentFragment.webView.getTitle(); } // Set the title for the selected Tab if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) { - getActionBar().getSelectedTab().setText(title); + getSupportActionBar().getSelectedTab().setText(title); } } @@ -517,16 +602,28 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T // This method gets a reference to the fragment, that is currently visible in the ViewPager private KiwixMobileFragment getCurrentVisibleFragment() { - return ((KiwixMobileFragment) mViewPagerAdapter. - getFragmentAtPosition(mViewPager.getCurrentItem())); + return ((KiwixMobileFragment) mViewPagerAdapter.getFragmentAtPosition(mViewPager.getCurrentItem())); } @Override public boolean onLongClick(View v) { - View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); mCurrentDraggedTab = (Integer) v.getTag(R.id.action_bar_tab_id); + if (newApi()) { + onLongClickOperation(v); + } else { + compatOnLongClickOperation(); + } + + return true; + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void onLongClickOperation(View v) { + + View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); + mTabsWidth = v.getWidth(); mTabsHeight = v.getHeight(); @@ -535,69 +632,21 @@ public class KiwixMobileActivity extends FragmentActivity implements ActionBar.T ClipData data = ClipData.newPlainText("", ""); v.startDrag(data, shadowBuilder, v, 0); - - return true; } - // Delete the current Tab, that is being dragged, if it hits the bounds of the Screen - @Override - public boolean onDrag(View v, DragEvent event) { + private void compatOnLongClickOperation() { - DisplayMetrics displaymetrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); + AlertDialog.Builder dialog = new AlertDialog.Builder(this); - // Get the height of the title bar - final int titleBarHeight; - - switch (displaymetrics.densityDpi) { - - case DisplayMetrics.DENSITY_HIGH: - titleBarHeight = 48; - break; - - case DisplayMetrics.DENSITY_MEDIUM: - titleBarHeight = 32; - break; - - case DisplayMetrics.DENSITY_LOW: - titleBarHeight = 24; - break; - - default: - titleBarHeight = 0; - } - - // Get the width and height of the screen - final int screenHeight = displaymetrics.heightPixels; - final int screenWidth = displaymetrics.widthPixels; - - // Get the current position of the View, that is being dragged - final int positionX = (int) event.getX(); - final int positionY = (int) event.getY(); - - if (event.getAction() == DragEvent.ACTION_DRAG_EXITED) { - - removeTabAt(mCurrentDraggedTab); - return true; - } - - if (event.getAction() == DragEvent.ACTION_DROP) { - - // Does it hit the boundries on the x-axis? - if ((positionX > screenWidth - (0.25 * mTabsWidth)) || - (positionX < (0.25 * mTabsWidth))) { - Log.i("kiwix", "Dragged out"); + dialog.setTitle(getString(R.string.delete_tab_title)); + dialog.setMessage(getString(R.string.delete_tab_message)); + dialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { removeTabAt(mCurrentDraggedTab); } - // Does it hit the boundries on the y-axis? - else if ((positionY > screenHeight - (0.25 * mTabsHeight)) || - ((positionY - titleBarHeight) < (0.5 * mTabsHeight))) { - Log.i("kiwix", "Dragged out"); - removeTabAt(mCurrentDraggedTab); - } - return true; - } - return false; + }); + dialog.setNegativeButton(android.R.string.no, null); + dialog.show(); } public class State { diff --git a/src/org/kiwix/kiwixmobile/KiwixMobileFragment.java b/src/org/kiwix/kiwixmobile/KiwixMobileFragment.java index 338f088ac..5aed0febb 100644 --- a/src/org/kiwix/kiwixmobile/KiwixMobileFragment.java +++ b/src/org/kiwix/kiwixmobile/KiwixMobileFragment.java @@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; @@ -32,6 +33,7 @@ import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -39,6 +41,7 @@ import android.os.Looper; import android.os.Message; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; +import android.support.v7.app.ActionBarActivity; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; @@ -85,6 +88,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import static org.kiwix.kiwixmobile.BackwardsCompatibilityTools.newApi; + public class KiwixMobileFragment extends Fragment { public static final String TAG_KIWIX = "kiwix"; @@ -183,14 +188,16 @@ public class KiwixMobileFragment extends Fragment { setUpWebView(); - setUpTabDeleteCross(); - setUpArticleSearchTextView(savedInstanceState); loadPrefs(); manageExternalLaunchAndRestoringViewState(savedInstanceState); + if (newApi()) { + setUpTabDeleteCross(); + } + return root; } @@ -296,8 +303,8 @@ public class KiwixMobileFragment extends Fragment { if (event.getAction() != MotionEvent.ACTION_UP) { return false; } - if (event.getX() > articleSearchtextView.getWidth() - articleSearchtextView.getPaddingRight() - - mClearIcon.getIntrinsicWidth()) { + if (event.getX() > articleSearchtextView.getWidth() + - articleSearchtextView.getPaddingRight() - mClearIcon.getIntrinsicWidth()) { articleSearchtextView.setText(""); articleSearchtextView.setCompoundDrawables(mSearchIcon, null, null, null); } @@ -316,8 +323,7 @@ public class KiwixMobileFragment extends Fragment { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { articleSearchtextView.setCompoundDrawables(mSearchIcon, null, - articleSearchtextView.getText().toString().equals("") ? null : mClearIcon, - null); + articleSearchtextView.getText().toString().equals("") ? null : mClearIcon, null); } @Override @@ -330,15 +336,19 @@ public class KiwixMobileFragment extends Fragment { }); // Create the adapter and set it to the AutoCompleteTextView - adapter = new AutoCompleteAdapter(getActivity(), - android.R.layout.simple_list_item_1); + if (newApi()) { + adapter = new AutoCompleteAdapter(getActivity(), android.R.layout.simple_list_item_1); + } else { + adapter = new AutoCompleteAdapter(getActivity(), R.layout.simple_list_item); + } + articleSearchtextView.setAdapter(adapter); articleSearchtextView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService( - Context.INPUT_METHOD_SERVICE); + InputMethodManager imm = (InputMethodManager) + getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(articleSearchtextView.getWindowToken(), 0); articleSearchtextView.setText(parent.getItemAtPosition(position).toString()); openArticleFromSearch(); @@ -347,8 +357,7 @@ public class KiwixMobileFragment extends Fragment { articleSearchtextView.setOnEditorActionListener(new OnEditorActionListener() { @Override - public boolean onEditorAction(TextView v, int actionId, - KeyEvent event) { + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { return openArticleFromSearch(); } }); @@ -356,6 +365,7 @@ public class KiwixMobileFragment extends Fragment { articleSearchtextView.setInputType(InputType.TYPE_CLASS_TEXT); } + @TargetApi(Build.VERSION_CODES.HONEYCOMB) private void setUpTabDeleteCross() { mTabDeleteCross.setOnDragListener(new View.OnDragListener() { @@ -618,7 +628,7 @@ public class KiwixMobileFragment extends Fragment { } break; case PREFERENCES_REQUEST_CODE: - if (resultCode == KiwixSettings.RESULT_RESTART) { + if (resultCode == KiwixSettingsActivity.RESULT_RESTART) { getActivity().finish(); startActivity(new Intent(getActivity(), KiwixMobileActivity.class)); } @@ -671,8 +681,7 @@ public class KiwixMobileFragment extends Fragment { // Pinch to zoom // This seems to suffer from a bug in Android. If you set to "false" this only apply after a restart of the app. Log.d(TAG_KIWIX, "pref_zoom_enabled value (" + pref_zoom_enabled + ")"); - webView.getSettings().setBuiltInZoomControls(true); - webView.getSettings().setDisplayZoomControls(pref_zoom_enabled); + webView.disableZoomControlls(pref_zoom_enabled); if (!isBacktotopEnabled) { mBackToTopButton.setVisibility(View.INVISIBLE); @@ -699,7 +708,7 @@ public class KiwixMobileFragment extends Fragment { } public void selectSettings() { - Intent i = new Intent(getActivity(), KiwixSettings.class); + Intent i = new Intent(getActivity(), KiwixSettingsActivity.class); startActivityForResult(i, PREFERENCES_REQUEST_CODE); } @@ -716,8 +725,8 @@ public class KiwixMobileFragment extends Fragment { // Move cursor to end articleSearchtextView.setSelection(articleSearchtextView.getText().length()); - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService( - Context.INPUT_METHOD_SERVICE); + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); } } @@ -747,7 +756,8 @@ public class KiwixMobileFragment extends Fragment { if (file.exists()) { if (ZimContentProvider.setZimFile(file.getAbsolutePath()) != null) { - getActivity().getActionBar().setSubtitle(ZimContentProvider.getZimFileTitle()); + ((ActionBarActivity) getActivity()).getSupportActionBar() + .setSubtitle(ZimContentProvider.getZimFileTitle()); // Apparently with webView.clearHistory() only history before currently (fully) // loaded page is cleared -> request clear, actual clear done after load. @@ -1060,10 +1070,9 @@ public class KiwixMobileFragment extends Fragment { failingUrl); // TODO apparently screws up back/forward webView.loadDataWithBaseURL("file://error", - "" + errorString + "", "text/html", "utf-8", - failingUrl); + "" + errorString + "", "text/html", "utf-8", failingUrl); String title = getResources().getString(R.string.app_name); - getActivity().getActionBar().setTitle(title); + ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(title); } @Override @@ -1075,12 +1084,13 @@ public class KiwixMobileFragment extends Fragment { title = webView.getTitle(); } - if (getActivity().getActionBar().getTabCount() < 2) { - getActivity().getActionBar().setTitle(title); + if (((ActionBarActivity) getActivity()).getSupportActionBar().getTabCount() < 2) { + ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(title); } - if (getActivity().getActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) { - getActivity().getActionBar().getSelectedTab().setText(title); + if (((ActionBarActivity) getActivity()).getSupportActionBar().getNavigationMode() + == ActionBar.NAVIGATION_MODE_TABS) { + ((ActionBarActivity) getActivity()).getSupportActionBar().getSelectedTab().setText(title); } // Workaround for #643 diff --git a/src/org/kiwix/kiwixmobile/KiwixSettings.java b/src/org/kiwix/kiwixmobile/KiwixSettings.java deleted file mode 100644 index af851f572..000000000 --- a/src/org/kiwix/kiwixmobile/KiwixSettings.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2013 Rashiq Ahmad - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -package org.kiwix.kiwixmobile; - -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Bundle; -import android.preference.EditTextPreference; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceChangeListener; -import android.preference.PreferenceFragment; - -import java.util.Locale; - -public class KiwixSettings extends Activity { - - public static final int RESULT_RESTART = 1236; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment()).commit(); - - new LanguageUtils(this).changeFont(getLayoutInflater()); - } - - public class PrefsFragment extends PreferenceFragment { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Load the preferences from an XML resource - addPreferencesFromResource(R.xml.preferences); - - prepareListPreferenceForAutoSummary("pref_zoom"); - setUpLanguageChooser("pref_language_chooser"); - setAppVersionNumber(); - } - - private void prepareListPreferenceForAutoSummary(String preferenceId) { - - ListPreference prefList = (ListPreference) findPreference(preferenceId); - - prefList.setDefaultValue(prefList.getEntryValues()[0]); - String summary = prefList.getValue(); - - if (summary == null) { - prefList.setValue((String) prefList.getEntryValues()[0]); - summary = prefList.getValue(); - } - - prefList.setSummary(prefList.getEntries()[prefList.findIndexOfValue(summary)]); - prefList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if (preference instanceof ListPreference) { - preference.setSummary(((ListPreference) preference) - .getEntries()[((ListPreference) preference) - .findIndexOfValue(newValue.toString())]); - } - return true; - } - }); - } - - private void setUpLanguageChooser(String preferenceId) { - - ListPreference languageList = (ListPreference) findPreference(preferenceId); - - LanguageUtils languageUtils = new LanguageUtils(getActivity()); - - languageList.setTitle(Locale.getDefault().getDisplayLanguage()); - - languageList.setEntries(languageUtils.getValues().toArray(new String[0])); - languageList.setEntryValues(languageUtils.getKeys().toArray(new String[0])); - - languageList.setDefaultValue(Locale.getDefault().toString()); - - languageList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - - if (!newValue.equals(Locale.getDefault().toString())) { - - LanguageUtils.handleLocaleChange(getActivity(), newValue.toString()); - // Request a restart when the user returns to the Activity, that called this Activity - setResult(RESULT_RESTART); - finish(); - startActivity(new Intent(getActivity(), KiwixSettings.class)); - } - return true; - } - }); - } - - private void setAppVersionNumber() { - String version; - - try { - version = getPackageManager().getPackageInfo("org.kiwix.kiwixmobile", 0).versionName; - } catch (NameNotFoundException e) { - return; - } - EditTextPreference versionPref = (EditTextPreference) findPreference("pref_version"); - versionPref.setSummary(version); - } - } -} \ No newline at end of file diff --git a/src/org/kiwix/kiwixmobile/KiwixSettingsActivity.java b/src/org/kiwix/kiwixmobile/KiwixSettingsActivity.java new file mode 100644 index 000000000..af4f55aa5 --- /dev/null +++ b/src/org/kiwix/kiwixmobile/KiwixSettingsActivity.java @@ -0,0 +1,117 @@ +/* + * Copyright 2013 Rashiq Ahmad + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +package org.kiwix.kiwixmobile; + +import android.content.Intent; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceActivity; + +import java.util.Locale; + +public class KiwixSettingsActivity extends PreferenceActivity { + + public static final int RESULT_RESTART = 1236; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + + prepareListPreferenceForAutoSummary("pref_zoom"); + setUpLanguageChooser("pref_language_chooser"); + setAppVersionNumber(); + new LanguageUtils(this).changeFont(getLayoutInflater()); + } + + private void prepareListPreferenceForAutoSummary(String preferenceId) { + + ListPreference prefList = (ListPreference) findPreference(preferenceId); + + prefList.setDefaultValue(prefList.getEntryValues()[0]); + String summary = prefList.getValue(); + + if (summary == null) { + prefList.setValue((String) prefList.getEntryValues()[0]); + summary = prefList.getValue(); + } + + prefList.setSummary(prefList.getEntries()[prefList.findIndexOfValue(summary)]); + prefList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (preference instanceof ListPreference) { + preference.setSummary(((ListPreference) preference) + .getEntries()[((ListPreference) preference) + .findIndexOfValue(newValue.toString())]); + } + return true; + } + }); + } + + private void setUpLanguageChooser(String preferenceId) { + + ListPreference languageList = (ListPreference) findPreference(preferenceId); + + LanguageUtils languageUtils = new LanguageUtils(KiwixSettingsActivity.this); + + languageList.setTitle(Locale.getDefault().getDisplayLanguage()); + + languageList.setEntries(languageUtils.getValues().toArray(new String[0])); + + languageList.setEntryValues(languageUtils.getKeys().toArray(new String[0])); + + languageList.setDefaultValue(Locale.getDefault().toString()); + + languageList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + + if (!newValue.equals(Locale.getDefault().toString())) { + + LanguageUtils.handleLocaleChange(KiwixSettingsActivity.this, newValue.toString()); + // Request a restart when the user returns to the Activity, that called this Activity + setResult(RESULT_RESTART); + finish(); + startActivity(new Intent(KiwixSettingsActivity.this, KiwixSettingsActivity.class)); + } + return true; + } + }); + } + + private void setAppVersionNumber() { + String version; + + try { + version = getPackageManager().getPackageInfo("org.kiwix.kiwixmobile", 0).versionName; + } catch (NameNotFoundException e) { + return; + } + EditTextPreference versionPref = (EditTextPreference) findPreference("pref_version"); + versionPref.setSummary(version); + } +} diff --git a/src/org/kiwix/kiwixmobile/KiwixWebView.java b/src/org/kiwix/kiwixmobile/KiwixWebView.java index 121f95527..539b16891 100644 --- a/src/org/kiwix/kiwixmobile/KiwixWebView.java +++ b/src/org/kiwix/kiwixmobile/KiwixWebView.java @@ -21,11 +21,16 @@ package org.kiwix.kiwixmobile; import android.content.Context; import android.util.AttributeSet; +import android.view.MotionEvent; import android.webkit.WebView; +import android.widget.ZoomButtonsController; -/* - * Custom version of link{@android.webkit.WebView} - * to get scroll positions for implimenting the Back to top +import java.lang.reflect.Method; + +import static org.kiwix.kiwixmobile.BackwardsCompatibilityTools.newApi; + +/** + * A custom WebView to get scroll positions for implimenting the Back-To-Top Button */ public class KiwixWebView extends WebView { @@ -33,6 +38,10 @@ public class KiwixWebView extends WebView { private OnLongClickListener mOnLongClickListener; + private ZoomButtonsController zoomControll = null; + + private boolean mDisableZoomControlls; + public KiwixWebView(Context context) { super(context); @@ -63,12 +72,45 @@ public class KiwixWebView extends WebView { int windowHeight = getMeasuredHeight(); int pages = getContentHeight() / windowHeight; int page = t / windowHeight; - //alert the listeners + + // Alert the listener if (mChangeListener != null) { mChangeListener.onPageChanged(page, pages); } } + public void disableZoomControlls(boolean disable) { + + mDisableZoomControlls = disable; + + if (newApi()) { + getSettings().setBuiltInZoomControls(true); + getSettings().setDisplayZoomControls(disable); + } else { + getZoomControlls(); + } + } + + // Use reflection to hide the zoom controlls + private void getZoomControlls() { + try { + Class webview = Class.forName("android.webkit.WebView"); + Method method = webview.getMethod("getZoomButtonsController"); + zoomControll = (ZoomButtonsController) method.invoke(this, null); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + super.onTouchEvent(ev); + if (zoomControll != null) { + zoomControll.setVisible(mDisableZoomControlls); + } + return true; + } + public void setOnPageChangedListener(OnPageChangeListener listener) { mChangeListener = listener; } diff --git a/src/org/kiwix/kiwixmobile/LanguageUtils.java b/src/org/kiwix/kiwixmobile/LanguageUtils.java index 941b1f2a9..e39d63b31 100644 --- a/src/org/kiwix/kiwixmobile/LanguageUtils.java +++ b/src/org/kiwix/kiwixmobile/LanguageUtils.java @@ -22,6 +22,7 @@ package org.kiwix.kiwixmobile; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; +import android.graphics.Color; import android.graphics.Typeface; import android.os.Handler; import android.preference.PreferenceManager; @@ -32,6 +33,7 @@ import android.view.InflateException; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; +import android.widget.Toast; import java.lang.reflect.Field; import java.util.ArrayList; @@ -160,11 +162,13 @@ public class LanguageUtils { layoutInflater.setFactory(new LayoutInflaterFactory(mContext, layoutInflater)); } catch (NoSuchFieldException e) { + Log.e("kiwix", "could not access private field of the LayoutInflater"); } catch (IllegalArgumentException e) { + Log.e("kiwix", "could not access private field of the LayoutInflater"); } catch (IllegalAccessException e) { - + Log.e("kiwix", "could not access private field of the LayoutInflater"); } } @@ -226,17 +230,17 @@ public class LanguageUtils { Log.d("kiwix", "Applying custom font"); // Reduce the text size - textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textView.getTextSize() - 3f); + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textView.getTextSize() - 2f); } }); return view; } catch (InflateException e) { - Log.e("kiwix", "Could not apply the custom font"); + Log.e("kiwix", "Could not apply the custom font to " + name + " " + e.getMessage()); } catch (ClassNotFoundException e) { - Log.e("kiwix", "Could not apply the custom font"); + Log.e("kiwix", "Could not apply the custom font to " + name + " " + e.getMessage()); } } @@ -245,12 +249,13 @@ public class LanguageUtils { // This method will determine which font will be applied to the not-supported-locale. // You can define exceptions to the default DejaVu font in the 'exceptions' Hashmap: + private String getTypeface() { // Define the exceptions to the rule. The font has to be placed in the assets folder. // Key: the language code; Value: the name of the font. HashMap exceptions = new HashMap(); - exceptions.put("my", "Parabaik.ttf"); + exceptions.put("my", "fonts/Parabaik.ttf"); // Check, if an exception applies to our current locale if (exceptions.containsKey(Locale.getDefault().getLanguage())) { @@ -258,7 +263,7 @@ public class LanguageUtils { } // Return the default font - return "DejaVuSansCondensed.ttf"; + return "fonts/DejaVuSansCondensed.ttf"; } } diff --git a/src/org/kiwix/kiwixmobile/ZimContentProvider.java b/src/org/kiwix/kiwixmobile/ZimContentProvider.java index 028f15058..e6f930f67 100644 --- a/src/org/kiwix/kiwixmobile/ZimContentProvider.java +++ b/src/org/kiwix/kiwixmobile/ZimContentProvider.java @@ -19,11 +19,6 @@ package org.kiwix.kiwixmobile; -import java.io.ByteArrayInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; - import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; @@ -32,223 +27,238 @@ import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor.AutoCloseOutputStream; import android.util.Log; +import java.io.ByteArrayInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; + public class ZimContentProvider extends ContentProvider { - public static final Uri CONTENT_URI = Uri.parse("content://org.kiwix.zim/"); - public static final Uri UI_URI = Uri.parse("content://org.kiwix.ui/"); - - private static String zimFileName; - private static JNIKiwix jniKiwix; - public synchronized static String setZimFile(String fileName) { - if (!jniKiwix.loadZIM(fileName)) { - Log.e("kiwix", "Unable to open the file " + fileName); - zimFileName = null; - } else { - zimFileName = fileName; - } - return zimFileName; - } + public static final Uri CONTENT_URI = Uri.parse("content://org.kiwix.zim/"); + + public static final Uri UI_URI = Uri.parse("content://org.kiwix.ui/"); + + private static String zimFileName; + + private static JNIKiwix jniKiwix; + + public synchronized static String setZimFile(String fileName) { + if (!jniKiwix.loadZIM(fileName)) { + Log.e("kiwix", "Unable to open the file " + fileName); + zimFileName = null; + } else { + zimFileName = fileName; + } + return zimFileName; + } + + public static String getZimFile() { + return zimFileName; + } + + public static String getZimFileTitle() { + if (jniKiwix == null || zimFileName == null) { + return null; + } else { + JNIKiwixString title = new JNIKiwixString(); + if (jniKiwix.getTitle(title)) { + return title.value; + } else { + return null; + } + } + } - public static String getZimFile() { - return zimFileName; - } - public static String getZimFileTitle() { - if (jniKiwix==null || zimFileName==null) - return null; - else { - JNIKiwixString title = new JNIKiwixString(); - if (jniKiwix.getTitle(title)) { - return title.value; - } - else return null; - } - } - public static String getMainPage() { - if (jniKiwix==null || zimFileName==null) - return null; - else { - return jniKiwix.getMainPage(); - } - } + if (jniKiwix == null || zimFileName == null) { + return null; + } else { + return jniKiwix.getMainPage(); + } + } public static String getId() { - if (jniKiwix==null || zimFileName==null) - return null; - else { - return jniKiwix.getId(); - } - } - - public static boolean searchSuggestions(String prefix, int count) { - if (jniKiwix==null || zimFileName==null) - return false; - else { - return jniKiwix.searchSuggestions(prefix, count); - } - } - - public static String getNextSuggestion() { - if (jniKiwix==null || zimFileName==null) - return null; - else { - JNIKiwixString title=new JNIKiwixString(); - if (jniKiwix.getNextSuggestion(title)) { - return title.value; - } - else { - return null; - } - } - } - - public static String getPageUrlFromTitle(String title) { - if (jniKiwix==null || zimFileName==null) - return null; - else { - JNIKiwixString url=new JNIKiwixString(); - if (jniKiwix.getPageUrlFromTitle(title, url)) { - return url.value; - } else { - return null; - } - } - } - - public static String getRandomArticleUrl() { - if (jniKiwix==null || zimFileName==null) - return null; - else { - JNIKiwixString url=new JNIKiwixString(); - if (jniKiwix.getRandomPage(url)) { - return url.value; - } else { - return null; - } - } - } - @Override - public boolean onCreate() { - jniKiwix = new JNIKiwix(); - - return (true); - } + if (jniKiwix == null || zimFileName == null) { + return null; + } else { + return jniKiwix.getId(); + } + } - @Override - public String getType(Uri uri) { - Log.w("kiwix", "ZimContentProvider.getType() (not implemented) called"); - return null; - } + public static boolean searchSuggestions(String prefix, int count) { + if (jniKiwix == null || zimFileName == null) { + return false; + } else { + return jniKiwix.searchSuggestions(prefix, count); + } + } - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - ParcelFileDescriptor[] pipe = null; + public static String getNextSuggestion() { + if (jniKiwix == null || zimFileName == null) { + return null; + } else { + JNIKiwixString title = new JNIKiwixString(); + if (jniKiwix.getNextSuggestion(title)) { + return title.value; + } else { + return null; + } + } + } - try { - pipe = ParcelFileDescriptor.createPipe(); - new TransferThread(jniKiwix, uri, new AutoCloseOutputStream( - pipe[1])).start(); - } catch (IOException e) { - Log.e(getClass().getSimpleName(), "Exception opening pipe", e); - throw new FileNotFoundException("Could not open pipe for: " - + uri.toString()); - } + public static String getPageUrlFromTitle(String title) { + if (jniKiwix == null || zimFileName == null) { + return null; + } else { + JNIKiwixString url = new JNIKiwixString(); + if (jniKiwix.getPageUrlFromTitle(title, url)) { + return url.value; + } else { + return null; + } + } + } - return (pipe[0]); - } + public static String getRandomArticleUrl() { + if (jniKiwix == null || zimFileName == null) { + return null; + } else { + JNIKiwixString url = new JNIKiwixString(); + if (jniKiwix.getRandomPage(url)) { + return url.value; + } else { + return null; + } + } + } - @Override - public Cursor query(Uri url, String[] projection, String selection, - String[] selectionArgs, String sort) { - throw new RuntimeException("Operation not supported"); - } + @Override + public boolean onCreate() { + jniKiwix = new JNIKiwix(); - @Override - public Uri insert(Uri uri, ContentValues initialValues) { - throw new RuntimeException("Operation not supported"); - } + return (true); + } - @Override - public int update(Uri uri, ContentValues values, String where, - String[] whereArgs) { - throw new RuntimeException("Operation not supported"); - } + @Override + public String getType(Uri uri) { + Log.w("kiwix", "ZimContentProvider.getType() (not implemented) called"); + return null; + } - @Override - public int delete(Uri uri, String where, String[] whereArgs) { - throw new RuntimeException("Operation not supported"); - } + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) + throws FileNotFoundException { + ParcelFileDescriptor[] pipe = null; - static class TransferThread extends Thread { + try { + pipe = ParcelFileDescriptor.createPipe(); + new TransferThread(jniKiwix, uri, new AutoCloseOutputStream( + pipe[1])).start(); + } catch (IOException e) { + Log.e(getClass().getSimpleName(), "Exception opening pipe", e); + throw new FileNotFoundException("Could not open pipe for: " + + uri.toString()); + } - Uri articleUri; - String articleZimUrl; - OutputStream out; - JNIKiwix jniKiwix; + return (pipe[0]); + } - TransferThread(JNIKiwix jniKiwix, Uri articleUri, OutputStream out) throws IOException { - this.articleUri = articleUri; - this.jniKiwix = jniKiwix; - Log.d("kiwix", - "Retrieving :" - + articleUri.toString()); - - String t = articleUri.toString(); - int pos = articleUri.toString().indexOf(CONTENT_URI.toString()); - if (pos != -1) - t = articleUri.toString().substring( - CONTENT_URI.toString().length()); - // Remove fragment (#...) as not supported by zimlib - pos = t.indexOf("#"); - if (pos != -1) { - t = t.substring(0, pos); - } - - this.out = out; - this.articleZimUrl = t; - } + @Override + public Cursor query(Uri url, String[] projection, String selection, + String[] selectionArgs, String sort) { + throw new RuntimeException("Operation not supported"); + } - @Override - public void run() { - byte[] buf = new byte[1024]; - int len; + @Override + public Uri insert(Uri uri, ContentValues initialValues) { + throw new RuntimeException("Operation not supported"); + } - try { - JNIKiwixString mime = new JNIKiwixString(); - JNIKiwixInt size = new JNIKiwixInt(); - byte[] data = jniKiwix.getContent(articleZimUrl, mime, size); - // Log.d("kiwix","articleDataByteArray:"+articleDataByteArray.toString()); - // ByteArrayInputStream articleDataInputStream = new - // ByteArrayInputStream(articleDataByteArray.toByteArray()); - // Log.d("kiwix","article data loaded from zime file"); + @Override + public int update(Uri uri, ContentValues values, String where, + String[] whereArgs) { + throw new RuntimeException("Operation not supported"); + } - //ByteArrayInputStream articleDataInputStream = new ByteArrayInputStream( - // articleDataByteArray.toByteArray()); - ByteArrayInputStream articleDataInputStream = new ByteArrayInputStream(data); - while ((len = articleDataInputStream.read(buf)) > 0) { - out.write(buf, 0, len); - } + @Override + public int delete(Uri uri, String where, String[] whereArgs) { + throw new RuntimeException("Operation not supported"); + } - articleDataInputStream.close(); - out.flush(); + static class TransferThread extends Thread { - Log.d("kiwix", "reading " + articleZimUrl - + "(mime "+mime.value+", size: "+size.value+") finished."); - } catch (IOException e) { - Log.e(getClass().getSimpleName(), "Exception reading article " - + articleZimUrl + " from zim file", e); - } catch (NullPointerException e) { - Log.e(getClass().getSimpleName(), "Exception reading article " - + articleZimUrl + " from zim file", e); + Uri articleUri; - } finally { - try { - out.close(); - } catch (IOException e) { - } + String articleZimUrl; - } - } - } + OutputStream out; + + JNIKiwix jniKiwix; + + TransferThread(JNIKiwix jniKiwix, Uri articleUri, OutputStream out) throws IOException { + this.articleUri = articleUri; + this.jniKiwix = jniKiwix; + Log.d("kiwix", + "Retrieving :" + + articleUri.toString()); + + String t = articleUri.toString(); + int pos = articleUri.toString().indexOf(CONTENT_URI.toString()); + if (pos != -1) { + t = articleUri.toString().substring( + CONTENT_URI.toString().length()); + } + // Remove fragment (#...) as not supported by zimlib + pos = t.indexOf("#"); + if (pos != -1) { + t = t.substring(0, pos); + } + + this.out = out; + this.articleZimUrl = t; + } + + @Override + public void run() { + byte[] buf = new byte[1024]; + int len; + + try { + JNIKiwixString mime = new JNIKiwixString(); + JNIKiwixInt size = new JNIKiwixInt(); + byte[] data = jniKiwix.getContent(articleZimUrl, mime, size); + // Log.d("kiwix","articleDataByteArray:"+articleDataByteArray.toString()); + // ByteArrayInputStream articleDataInputStream = new + // ByteArrayInputStream(articleDataByteArray.toByteArray()); + // Log.d("kiwix","article data loaded from zime file"); + + //ByteArrayInputStream articleDataInputStream = new ByteArrayInputStream( + // articleDataByteArray.toByteArray()); + ByteArrayInputStream articleDataInputStream = new ByteArrayInputStream(data); + while ((len = articleDataInputStream.read(buf)) > 0) { + out.write(buf, 0, len); + } + + articleDataInputStream.close(); + out.flush(); + + Log.d("kiwix", "reading " + articleZimUrl + + "(mime " + mime.value + ", size: " + size.value + ") finished."); + } catch (IOException e) { + Log.e(getClass().getSimpleName(), "Exception reading article " + + articleZimUrl + " from zim file", e); + } catch (NullPointerException e) { + Log.e(getClass().getSimpleName(), "Exception reading article " + + articleZimUrl + " from zim file", e); + + } finally { + try { + out.close(); + } catch (IOException e) { + + } + + } + } + } } \ No newline at end of file diff --git a/src/org/kiwix/kiwixmobile/ZimFileSelectActivity.java b/src/org/kiwix/kiwixmobile/ZimFileSelectActivity.java index 9426913b3..e549f7159 100644 --- a/src/org/kiwix/kiwixmobile/ZimFileSelectActivity.java +++ b/src/org/kiwix/kiwixmobile/ZimFileSelectActivity.java @@ -19,6 +19,7 @@ package org.kiwix.kiwixmobile; +import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -27,17 +28,18 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; -import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.SimpleCursorAdapter; +import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.animation.AlphaAnimation; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; @@ -45,12 +47,13 @@ import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; +import android.widget.Toast; import java.io.File; import java.util.ArrayList; import java.util.List; -public class ZimFileSelectActivity extends FragmentActivity +public class ZimFileSelectActivity extends ActionBarActivity implements LoaderManager.LoaderCallbacks, OnItemClickListener { private static final int LOADER_ID = 0x02; @@ -80,11 +83,12 @@ public class ZimFileSelectActivity extends FragmentActivity mProgressBar = (ProgressBar) findViewById(R.id.progressBar); mProgressBarMessage = (TextView) findViewById(R.id.progressbar_message); mZimFileList = (ListView) findViewById(R.id.zimfilelist); + mFiles = new ArrayList(); + + mZimFileList.setOnItemClickListener(this); mProgressBar.setVisibility(View.VISIBLE); - // mZimFileList.setAlpha(0.4f); - - mFiles = new ArrayList(); + setAlpha(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { startQuery(); @@ -93,8 +97,10 @@ public class ZimFileSelectActivity extends FragmentActivity } } + @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public Loader onCreateLoader(int i, Bundle bundle) { + Uri uri = MediaStore.Files.getContentUri("external"); String[] projection = { @@ -137,7 +143,7 @@ public class ZimFileSelectActivity extends FragmentActivity if (mProgressBarMessage.getVisibility() == View.GONE) { mProgressBar.setVisibility(View.GONE); - // mZimFileList.setAlpha(1f); + setAlpha(false); } mCursorAdapter.notifyDataSetChanged(); @@ -241,8 +247,6 @@ public class ZimFileSelectActivity extends FragmentActivity // Flags for the Adapter Adapter.NO_SELECTION); - mZimFileList.setOnItemClickListener(this); - getSupportLoaderManager().initLoader(LOADER_ID, null, this); } @@ -290,6 +294,21 @@ public class ZimFileSelectActivity extends FragmentActivity } } + // Make the View transparent or opaque + private void setAlpha(boolean transparent) { + + float viewTransparency = transparent ? 0.4F : 1F; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mZimFileList.setAlpha(viewTransparency); + } else { + AlphaAnimation alpha = new AlphaAnimation(viewTransparency, viewTransparency); + alpha.setDuration(0); + alpha.setFillAfter(true); + mZimFileList.startAnimation(alpha); + } + } + // The Adapter for the ListView for when the ListView is populated with the rescanned files private class RescanDataAdapter extends ArrayAdapter { @@ -336,7 +355,7 @@ public class ZimFileSelectActivity extends FragmentActivity mProgressBarMessage.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.VISIBLE); - // mZimFileList.setAlpha(0.4f); + setAlpha(true); super.onPreExecute(); } @@ -356,12 +375,11 @@ public class ZimFileSelectActivity extends FragmentActivity mProgressBarMessage.setVisibility(View.GONE); mProgressBar.setVisibility(View.GONE); - // mZimFileList.setAlpha(1f); + setAlpha(false); new FileWriter(ZimFileSelectActivity.this).saveArray(mFiles); super.onPostExecute(result); } - } }