1package org.opencv.android;
2
3import java.io.File;
4import java.util.StringTokenizer;
5
6import org.opencv.core.Core;
7import org.opencv.engine.OpenCVEngineInterface;
8
9import android.content.ComponentName;
10import android.content.Context;
11import android.content.Intent;
12import android.content.ServiceConnection;
13import android.net.Uri;
14import android.os.IBinder;
15import android.os.RemoteException;
16import android.util.Log;
17
18class AsyncServiceHelper
19{
20    public static boolean initOpenCV(String Version, final Context AppContext,
21            final LoaderCallbackInterface Callback)
22    {
23        AsyncServiceHelper helper = new AsyncServiceHelper(Version, AppContext, Callback);
24        Intent intent = new Intent("org.opencv.engine.BIND");
25        intent.setPackage("org.opencv.engine");
26        if (AppContext.bindService(intent, helper.mServiceConnection, Context.BIND_AUTO_CREATE))
27        {
28            return true;
29        }
30        else
31        {
32            AppContext.unbindService(helper.mServiceConnection);
33            InstallService(AppContext, Callback);
34            return false;
35        }
36    }
37
38    protected AsyncServiceHelper(String Version, Context AppContext, LoaderCallbackInterface Callback)
39    {
40        mOpenCVersion = Version;
41        mUserAppCallback = Callback;
42        mAppContext = AppContext;
43    }
44
45    protected static final String TAG = "OpenCVManager/Helper";
46    protected static final int MINIMUM_ENGINE_VERSION = 2;
47    protected OpenCVEngineInterface mEngineService;
48    protected LoaderCallbackInterface mUserAppCallback;
49    protected String mOpenCVersion;
50    protected Context mAppContext;
51    protected static boolean mServiceInstallationProgress = false;
52    protected static boolean mLibraryInstallationProgress = false;
53
54    protected static boolean InstallServiceQuiet(Context context)
55    {
56        boolean result = true;
57        try
58        {
59            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(OPEN_CV_SERVICE_URL));
60            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
61            context.startActivity(intent);
62        }
63        catch(Exception e)
64        {
65            result = false;
66        }
67
68        return result;
69    }
70
71    protected static void InstallService(final Context AppContext, final LoaderCallbackInterface Callback)
72    {
73        if (!mServiceInstallationProgress)
74        {
75                Log.d(TAG, "Request new service installation");
76                InstallCallbackInterface InstallQuery = new InstallCallbackInterface() {
77                private LoaderCallbackInterface mUserAppCallback = Callback;
78                public String getPackageName()
79                {
80                    return "OpenCV Manager";
81                }
82                public void install() {
83                    Log.d(TAG, "Trying to install OpenCV Manager via Google Play");
84
85                    boolean result = InstallServiceQuiet(AppContext);
86                    if (result)
87                    {
88                        mServiceInstallationProgress = true;
89                        Log.d(TAG, "Package installation started");
90                    }
91                    else
92                    {
93                        Log.d(TAG, "OpenCV package was not installed!");
94                        int Status = LoaderCallbackInterface.MARKET_ERROR;
95                        Log.d(TAG, "Init finished with status " + Status);
96                        Log.d(TAG, "Unbind from service");
97                        Log.d(TAG, "Calling using callback");
98                        mUserAppCallback.onManagerConnected(Status);
99                    }
100                }
101
102                public void cancel()
103                {
104                    Log.d(TAG, "OpenCV library installation was canceled");
105                    int Status = LoaderCallbackInterface.INSTALL_CANCELED;
106                    Log.d(TAG, "Init finished with status " + Status);
107                    Log.d(TAG, "Calling using callback");
108                    mUserAppCallback.onManagerConnected(Status);
109                }
110
111                public void wait_install()
112                {
113                    Log.e(TAG, "Instalation was not started! Nothing to wait!");
114                }
115            };
116
117            Callback.onPackageInstall(InstallCallbackInterface.NEW_INSTALLATION, InstallQuery);
118        }
119        else
120        {
121            Log.d(TAG, "Waiting current installation process");
122            InstallCallbackInterface WaitQuery = new InstallCallbackInterface() {
123                private LoaderCallbackInterface mUserAppCallback = Callback;
124                public String getPackageName()
125                {
126                    return "OpenCV Manager";
127                }
128                public void install()
129                {
130                    Log.e(TAG, "Nothing to install we just wait current installation");
131                }
132                public void cancel()
133                {
134                    Log.d(TAG, "Wating for OpenCV canceled by user");
135                    mServiceInstallationProgress = false;
136                    int Status = LoaderCallbackInterface.INSTALL_CANCELED;
137                    Log.d(TAG, "Init finished with status " + Status);
138                    Log.d(TAG, "Calling using callback");
139                    mUserAppCallback.onManagerConnected(Status);
140                }
141                public void wait_install()
142                {
143                     InstallServiceQuiet(AppContext);
144                }
145            };
146
147            Callback.onPackageInstall(InstallCallbackInterface.INSTALLATION_PROGRESS, WaitQuery);
148        }
149    }
150
151    /**
152     *  URL of OpenCV Manager page on Google Play Market.
153     */
154    protected static final String OPEN_CV_SERVICE_URL = "market://details?id=org.opencv.engine";
155
156    protected ServiceConnection mServiceConnection = new ServiceConnection()
157    {
158        public void onServiceConnected(ComponentName className, IBinder service)
159        {
160            Log.d(TAG, "Service connection created");
161            mEngineService = OpenCVEngineInterface.Stub.asInterface(service);
162            if (null == mEngineService)
163            {
164                Log.d(TAG, "OpenCV Manager Service connection fails. May be service was not installed?");
165                InstallService(mAppContext, mUserAppCallback);
166            }
167            else
168            {
169                mServiceInstallationProgress = false;
170                try
171                {
172                    if (mEngineService.getEngineVersion() < MINIMUM_ENGINE_VERSION)
173                    {
174                        Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INCOMPATIBLE_MANAGER_VERSION);
175                        Log.d(TAG, "Unbind from service");
176                        mAppContext.unbindService(mServiceConnection);
177                        Log.d(TAG, "Calling using callback");
178                        mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INCOMPATIBLE_MANAGER_VERSION);
179                        return;
180                    }
181
182                    Log.d(TAG, "Trying to get library path");
183                    String path = mEngineService.getLibPathByVersion(mOpenCVersion);
184                    if ((null == path) || (path.length() == 0))
185                    {
186                        if (!mLibraryInstallationProgress)
187                        {
188                            InstallCallbackInterface InstallQuery = new InstallCallbackInterface() {
189                                public String getPackageName()
190                                {
191                                    return "OpenCV library";
192                                }
193                                public void install() {
194                                    Log.d(TAG, "Trying to install OpenCV lib via Google Play");
195                                    try
196                                    {
197                                        if (mEngineService.installVersion(mOpenCVersion))
198                                        {
199                                            mLibraryInstallationProgress = true;
200                                            Log.d(TAG, "Package installation statred");
201                                            Log.d(TAG, "Unbind from service");
202                                            mAppContext.unbindService(mServiceConnection);
203                                        }
204                                        else
205                                        {
206                                            Log.d(TAG, "OpenCV package was not installed!");
207                                            Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.MARKET_ERROR);
208                                            Log.d(TAG, "Unbind from service");
209                                            mAppContext.unbindService(mServiceConnection);
210                                            Log.d(TAG, "Calling using callback");
211                                            mUserAppCallback.onManagerConnected(LoaderCallbackInterface.MARKET_ERROR);
212                                        }
213                                    } catch (RemoteException e) {
214                                        e.printStackTrace();;
215                                        Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INIT_FAILED);
216                                        Log.d(TAG, "Unbind from service");
217                                        mAppContext.unbindService(mServiceConnection);
218                                        Log.d(TAG, "Calling using callback");
219                                        mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INIT_FAILED);
220                                    }
221                                }
222                                public void cancel() {
223                                    Log.d(TAG, "OpenCV library installation was canceled");
224                                    Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INSTALL_CANCELED);
225                                    Log.d(TAG, "Unbind from service");
226                                    mAppContext.unbindService(mServiceConnection);
227                                    Log.d(TAG, "Calling using callback");
228                                    mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INSTALL_CANCELED);
229                                }
230                                public void wait_install() {
231                                    Log.e(TAG, "Instalation was not started! Nothing to wait!");
232                                }
233                            };
234
235                            mUserAppCallback.onPackageInstall(InstallCallbackInterface.NEW_INSTALLATION, InstallQuery);
236                        }
237                        else
238                        {
239                            InstallCallbackInterface WaitQuery = new InstallCallbackInterface() {
240                                public String getPackageName()
241                                {
242                                    return "OpenCV library";
243                                }
244
245                                public void install() {
246                                    Log.e(TAG, "Nothing to install we just wait current installation");
247                                }
248                                public void cancel()
249                                {
250                                    Log.d(TAG, "OpenCV library installation was canceled");
251                                    mLibraryInstallationProgress = false;
252                                    Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INSTALL_CANCELED);
253                                    Log.d(TAG, "Unbind from service");
254                                    mAppContext.unbindService(mServiceConnection);
255                                    Log.d(TAG, "Calling using callback");
256                                        mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INSTALL_CANCELED);
257                                }
258                                public void wait_install() {
259                                    Log.d(TAG, "Waiting for current installation");
260                                    try
261                                    {
262                                        if (!mEngineService.installVersion(mOpenCVersion))
263                                        {
264                                            Log.d(TAG, "OpenCV package was not installed!");
265                                            Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.MARKET_ERROR);
266                                            Log.d(TAG, "Calling using callback");
267                                            mUserAppCallback.onManagerConnected(LoaderCallbackInterface.MARKET_ERROR);
268                                        }
269                                        else
270                                        {
271                                            Log.d(TAG, "Wating for package installation");
272                                        }
273
274                                        Log.d(TAG, "Unbind from service");
275                                        mAppContext.unbindService(mServiceConnection);
276
277                                    } catch (RemoteException e) {
278                                        e.printStackTrace();
279                                        Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INIT_FAILED);
280                                        Log.d(TAG, "Unbind from service");
281                                        mAppContext.unbindService(mServiceConnection);
282                                        Log.d(TAG, "Calling using callback");
283                                        mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INIT_FAILED);
284                                    }
285                               }
286                            };
287
288                            mUserAppCallback.onPackageInstall(InstallCallbackInterface.INSTALLATION_PROGRESS, WaitQuery);
289                        }
290                        return;
291                    }
292                    else
293                    {
294                        Log.d(TAG, "Trying to get library list");
295                        mLibraryInstallationProgress = false;
296                        String libs = mEngineService.getLibraryList(mOpenCVersion);
297                        Log.d(TAG, "Library list: \"" + libs + "\"");
298                        Log.d(TAG, "First attempt to load libs");
299                        int status;
300                        if (initOpenCVLibs(path, libs))
301                        {
302                            Log.d(TAG, "First attempt to load libs is OK");
303                            String eol = System.getProperty("line.separator");
304                            for (String str : Core.getBuildInformation().split(eol))
305                                Log.i(TAG, str);
306
307                            status = LoaderCallbackInterface.SUCCESS;
308                        }
309                        else
310                        {
311                            Log.d(TAG, "First attempt to load libs fails");
312                            status = LoaderCallbackInterface.INIT_FAILED;
313                        }
314
315                        Log.d(TAG, "Init finished with status " + status);
316                        Log.d(TAG, "Unbind from service");
317                        mAppContext.unbindService(mServiceConnection);
318                        Log.d(TAG, "Calling using callback");
319                        mUserAppCallback.onManagerConnected(status);
320                    }
321                }
322                catch (RemoteException e)
323                {
324                    e.printStackTrace();
325                    Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INIT_FAILED);
326                    Log.d(TAG, "Unbind from service");
327                    mAppContext.unbindService(mServiceConnection);
328                    Log.d(TAG, "Calling using callback");
329                    mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INIT_FAILED);
330                }
331            }
332        }
333
334        public void onServiceDisconnected(ComponentName className)
335        {
336            mEngineService = null;
337        }
338    };
339
340    private boolean loadLibrary(String AbsPath)
341    {
342        boolean result = true;
343
344        Log.d(TAG, "Trying to load library " + AbsPath);
345        try
346        {
347            System.load(AbsPath);
348            Log.d(TAG, "OpenCV libs init was ok!");
349        }
350        catch(UnsatisfiedLinkError e)
351        {
352            Log.d(TAG, "Cannot load library \"" + AbsPath + "\"");
353            e.printStackTrace();
354            result &= false;
355        }
356
357        return result;
358    }
359
360    private boolean initOpenCVLibs(String Path, String Libs)
361    {
362        Log.d(TAG, "Trying to init OpenCV libs");
363        if ((null != Path) && (Path.length() != 0))
364        {
365            boolean result = true;
366            if ((null != Libs) && (Libs.length() != 0))
367            {
368                Log.d(TAG, "Trying to load libs by dependency list");
369                StringTokenizer splitter = new StringTokenizer(Libs, ";");
370                while(splitter.hasMoreTokens())
371                {
372                    String AbsLibraryPath = Path + File.separator + splitter.nextToken();
373                    result &= loadLibrary(AbsLibraryPath);
374                }
375            }
376            else
377            {
378                // If the dependencies list is not defined or empty.
379                String AbsLibraryPath = Path + File.separator + "libopencv_java.so";
380                result &= loadLibrary(AbsLibraryPath);
381            }
382
383            return result;
384        }
385        else
386        {
387            Log.d(TAG, "Library path \"" + Path + "\" is empty");
388            return false;
389        }
390    }
391}
392