Developer Tutorial - Android

Getting Started

Add RSOfflinePlayer.jar to your project and make sure it is linked in your IDE.

Authentication

Authentication for the SDK is handled by the host application and not the Rustici Engine. This is the most flexible solution for adding the SDK to existing applications as well as new projects. The host application will handle the user login and will provide any necessary authorization details to the SDK when required.

Playing Content

To play the offline package, a RSOfflinePlayer object needs to be created by supplying a valid Rustici Engine ExternalPackageId, ExternalRegistrationId and ExternalConfiguration to the service along with the remote Rustici Engine URL and paths.

rsop.initWithPackageId(packageItem.packageId,"RegistrationApiId|1006!InstanceId|0", "", "12", kRemoteServerUrl, remotePathsForInit, remoteCredentialsForInit, isOnline,new RSOfflinePlayer.initPackageInterface(){
       @Override
       public void completionBlock() {
           Log.d("completion Block", "the url = " + rsop.packageLaunchUrl);
           WebView webView = (WebView) findViewById(R.id.myWebView);
           webView.getSettings().setJavaScriptEnabled(true);
           webView.getSettings().setSupportMultipleWindows(true);
           webView.getSettings().setDomStorageEnabled(true);

           MyJavaScriptInterface javaInterface = new MyJavaScriptInterface();
           webView.addJavascriptInterface(javaInterface, "injectedObject");
           webView.setWebChromeClient(new WebChromeClient() {
               public void onProgressChanged(WebView view, int progress) {
               }
               @Override
               public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, android.os.Message resultMsg)
               {
                   RelativeLayout contentContainer = (RelativeLayout) findViewById(R.id.contentContainer);
                   contentContainer.removeAllViews();

                   WebView childView = new WebView(mContext);
                   childView.getSettings().setJavaScriptEnabled(true);
                   childView.setWebChromeClient(this);
                   childView.setWebViewClient(new WebViewClient());
                   childView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

                   contentContainer.addView(childView);
                   WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
                   transport.setWebView(childView);
                   resultMsg.sendToTarget();
                   return true;
               }
           });

           webView.setWebViewClient(new WebViewClient() {
               public void onPageStarted(WebView view, String url, Bitmap favicon) {
                   super.onPageStarted(view, url, favicon);
                   Log.d("onPageStarted","url is = " + url);
               }
               public void onPageFinished(WebView view, String url) {
                   super.onPageFinished(view, url);
                   Log.d("onPageFinished","url is = " + url);
                   if(url.contains("results.html"))
                   {
                       view.loadUrl("javascript:( function () { var resultSrc = getRuntimeXml(); window.injectedObject.getRuntimeXml(resultSrc); } ) ()");
                       view.loadUrl("javascript:( function () { var resultSrc = getRegistrationJson(); window.injectedObject.getRegistrationJson(resultSrc); } ) ()");
                   }
               }
               public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                   super.onReceivedError(view, errorCode, description, failingUrl);
                   // Do something here
               }
           });
           // load the package start page into the WebView
           webView.loadUrl("file:///" + rsop.packageLaunchUrl);
       }

       @Override
       public void errorBlock()
       {
           Log.d("failure Block", "error");
       }
   });

Syncing Results

The SDK relies on the host application to create a UIWebView and navigate to the rsop.packageLaunchUrl as the start page. When the host application wants to sync the course data, it grabs the current values from the UIWebView’s content and sends it to the SDK for syncing. The host application supplies the isOnline value to allow various definitions of ‘online’ to be determined by the host application.

 class MyJavaScriptInterface {
     public void getRuntimeXml(String jsResult) {
        runtimeXml = jsResult;
     }
     public void getRegistrationJson(String jsResult) {
         attemptInfo = jsResult;
         rsop.syncCurrentSessionWithAttemptInfo(attemptInfo,runtimeXml,null,isOnline,new RSOfflinePlayer.syncCurrentSessionInterface(){
             @Override
             public void completionBlock()
             {
                 Log.d("syncCurrentSessionWithAttemptInfo completion Block", "we're done");
             }
             @Override
             public void errorBlock()
             {
                 Log.d("syncCurrentSessionWithAttemptInfo errorBlock", "sad face");
             }
         });
     }
 }

Getting Current Device Status

To get the current SCORM status for a registration, you can use the RSOfflinePlayer’s getCurrentStatus service. If you are offline, the most recent results from the local datastore are returned. If you are online, the data will be pulled from the Rustici Engine server and then checked against the latest local results to ensure the most recent or completed attempt is used.

rsop.getCurrentStatusWithCompletionBlock(new RSOfflinePlayer.getCurrentStatusInterface() {
     @Override
     public void completionBlock(Map<String, Object> stringObjectMap) {
         //display status
     }

     @Override
     public void errorBlock() {
         //handle error
     }
});

Deleting Local Content

The host application can use the SDK to delete content from the device when the user is finished with it and synced the results back to the Rustici Engine. Using RSOfflinePlayer’s deletePackage service will delete the package folder from the local filesystem as well as all of the session information in the datastore.

Special measures should be taken by the host application to not allow this for multi-user setups where one user could delete the package while another is still using it.

catalog.deletePackageWithCompletionBlock(itemToDelete, new RSOfflineCatalog.deletePackageInterface() {
       @Override
       public void completionBlock() {
           Log.d("deletePackage", "completionBlock");
       }
   });

results matching ""

    No results matching ""