Ads

Thursday, November 28, 2013

Android Multi Image Picker Module

Multi Image Picker module helps to select multiple images from Gallery.

This module developed from existing Android open source library MultipleImagePick. And it uses Universal image loader library for asynchronous loading and caching.

Multiple Image Picker Screen

Features and Benefits:
  • Select multiple images - Option to select multiple images from Gallery and fast scroll over the Gallery
  • Maximum selection limit - Option to set maximum image selection limit
  • Custom button title and error message - There is a option to customize button title and error message
  • Method for scale down the bitmap - To avoid out of memory issue, this module has in build bitmap scale down method
  • Callback methods - Success, error and cancel callback methods

Usage: 
var gallerypicker = require('titutorial.gallerypicker');
gallerypicker.openGallery({
    cancelButtonTitle: "Cancel",
    doneButtonTitle: "Okay",
    title: "Custom Gallery",
    errorMessage: "Limit reached",
    limit: 10,
    success: function (e) {
        Ti.API.info("response is => " + JSON.stringify(e));
        var imgArray = e.filePath.split(",");

        for (var i = 0; i < imgArray.length; i++) {
            if (imgArray[i]) {
                var imgView = Ti.UI.createImageView({
                    left: '10dp',
                    top: '10dp',
                    image: gallerypicker.decodeBitmapResource(imgArray[i], 100, 100)
                });
                imageHolder.add(imgView);
            }
        }
    },
    error: function (e) {
        alert("error " + JSON.stringify(e));
    }
});

Download:
Source code : https://github.com/railskarthi/TiMultiImagePicker
Module : https://marketplace.appcelerator.com/apps/7215?1782767416

Tuesday, November 5, 2013

Android Module Development - Part 5

This is the follow up post from Android Module Development series. Today I am
going to continue with next topic which is Using XML layouts in modules.
  1. Understanding methods, properties, constants and module life cycle
  2. Using event listeners and callbacks in Module
  3. Converting native control into Titanium view
  4. Accessing module and app resources
  5. Using XML layouts in modules
Usually in native Android development, we will define out user interface and layouts in xml file. Same thing we can implement in Titanium Android module also. For that we have to use LayoutInflater.

LayoutInflater class is used to instantiate layout XML file into its corresponding View objects. In other words, it takes as input an XML file and builds the View objects from it.

Lets consider our RatingBar module, here I am using xml layout file (raingbar_layout.xml) to create RatingBar with custom styles. In module I can access the xml layout elements in following way
//declaration
View raingBarWrapper;
int resId_raingBarHolder = -1, resId_ratingBar = -1;

//fetching app package name and resources 
String packageName = proxy.getActivity().getPackageName();
Resources resources = proxy.getActivity().getResources();

//fetching resource id
resId_raingBarHolder = resources.getIdentifier("raingbar_layout", "layout", packageName);
resId_ratingBar = resources.getIdentifier("ratingbar_default","id", packageName);

LayoutInflater inflater = LayoutInflater.from(getActivity());
//inflating "raingbar_layout" xml file
raingBarWrapper = inflater.inflate(resId_raingBarHolder, null);

//getting reference to RatingBar component in layout
ratingBar = (RatingBar) raingBarWrapper.findViewById(resId_ratingBar);
setNativeView(raingBarWrapper);

//adding properties to RatingBar component
ratingBar.setNumStars(stars);
ratingBar.setStepSize(stepSize);
ratingBar.setRating(rating);

XML layout file (raingbar_layout.xml)

 


Source Code:
You can download entire RatingBar module source code here https://github.com/railskarthi/Ratingbar

Thursday, October 24, 2013

Android Module Development - Part 4

This is the follow up post from Android Module Development series. Today I am going to continue with next topic which is Accessing module and app resources.
  1. Understanding methods, properties, constants and module life cycle
  2. Using event listeners and callbacks in Module
  3. Converting native control into Titanium view
  4. Accessing module and app resources
  5. Using XML layouts in modules
In Android module we can able to access resources from both module and application.

1. Accessing resource from Module
Let assume that you have few image resource in your module directory and if you want to access them, you can do that in following way
//creating new button
Button moduleButton = new Button(proxy.getActivity());  
moduleButton.setText("Image from module");  
moduleButton.setTextSize(20);  

//since we can't access R.java in Titanium module, we are getting the 
//resource id using packageName and resource type
String packageName = proxy.getActivity().getPackageName();
Resources resources = proxy.getActivity().getResources();

//getIdentifier method will return the resource id 
int textStyle = resources.getIdentifier("facebook_loginbutton_blue", "drawable", packageName);
moduleButton.setBackgroundResource(textStyle);

2. Accessing resource from Application
For example if you want to pass an image resource from your application to module, you can do that in following way
//creating new image button
ImageButton appButton = new ImageButton(proxy.getActivity());  

//getting the blob object of the application image
TiBlob imgObj = loadImageFromApplication(imageUrl);

//creating the bitmap from the blob object
TiDrawableReference ref = TiDrawableReference.fromBlob(proxy.getActivity(), imgObj);
appButton.setImageBitmap(ref.getBitmap());
Here loadImageFromApplication method takes input as image file path and it convert the application image into blob object.
public TiBlob loadImageFromApplication(String imageName) {
 TiBlob result = null;
 try {
  // Load the image from the application assets
  String url = getPathToApplicationAsset(imageName);
  TiBaseFile file = TiFileFactory.createTitaniumFile(
    new String[] { url }, false);
  Bitmap bitmap = TiUIHelper.createBitmap(file.getInputStream());

  // The bitmap must be converted to a TiBlob before returning
  result = TiBlob.blobFromImage(bitmap);
 } catch (IOException e) {
  Log.e(TAG, " EXCEPTION - IO");
 }
 return result;
}
Here getPathToApplicationAsset method takes input as image file path and it locates the resource relative to the application resources folder. It return the application asset url.
private String getPathToApplicationAsset(String assetName) {
 // The url for an application asset can be created by resolving the specified
 // path with the proxy context. This locates a resource relative to the
 // application resources folder
 String result = resolveUrl(null, assetName);

 return result;
}
In Javascript layer
var demo3 = require('titutorial.demo3');
var proxy = demo3.createExample({
 imageUrl : "icon.png"
});
win.add(proxy);
Source Code:
You can download entire module source code here https://github.com/TiTutorial/demo-android-module-3

Continue with part 5 

Thursday, October 17, 2013

Android Module Development - Part 3

This is the follow up post from Android Module Development series. Toady I am going to continue with next topic which is Converting native control into Titanium view.
  1. Understanding methods, properties, constants and module life cycle
  2. Using event listeners and callbacks in Module
  3. Converting native control into Titanium view
  4. Accessing module and app resources
  5. Using XML layouts in modules

In Titanium module we can convert native controls into Titanium view using  setNativeView method. setNativeView sets the nativeView to view.

For example, here I am going to convert Android native RatingBar extension to titanium view. Add below code in your ExampleProxy.java file

RatingBar rb;

private class ExampleView extends TiUIView {
 public ExampleView(TiViewProxy proxy) {
  super(proxy);

  // layoutParams for holder view
  LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
    LayoutParams.WRAP_CONTENT);
  // holder view
  LinearLayout holder = new LinearLayout(proxy.getActivity());
  holder.setLayoutParams(lp);

  // ratingbar widget
  rb = new RatingBar(proxy.getActivity());
  rb.setNumStars(5);
  rb.setStepSize(1);
  rb.setRating(2);

  // adding ratingbar to holder view
  holder.addView(rb);
  // setNativeView sets the nativeView to ratingbar view
  setNativeView(holder);
 }

 @Override
 public void processProperties(KrollDict d) {
  super.processProperties(d);
 }
}
In Javascript
var demo2 = require('titutorial.demo2');

var proxy = demo2.createExample({
 height : '65dp',
 top: '50dp',
 backgroundColor:'orange'
});
win.add(proxy);

Here createExample method will accept following properties height, width, left, top and bottom. Similar to RatingBar extension, we can also convert other native controls into titanium view using setNativeView method.

Output Screen:
Module Output Screen

Source Code:
You can download entire module source code here https://github.com/TiTutorial/demo-android-module-2  

Continue with part 4

Wednesday, October 9, 2013

Android Module Development - Part 2

Last week I started  a series of  articles regarding Android Module Development. Toady I am going to continue with next topic which is Using event listeners and callbacks in Module
  1. Understanding methods, properties, constants and module life cycle
  2. Using event listeners and callbacks in Module
  3. Converting native control into Titanium view
  4. Accessing module and app resources
  5. Using XML layouts in modules
Callbacks

During asynchronous operation, if we want to pass the data to javascript layer we have to use callbacks. It will call the particular method to send the data back to javascript layer. For example like onError, onSuccess. Callback will be invoked only once.

Example

Lets consider AudioRecorder module here I am using success and error callbacks, which will be called either on success or failure of audio recording process. It will be invoked only once.

In Module
// initializing callbacks
private KrollFunction successCallback = null;
private KrollFunction errorCallback = null;

// method to invoke success callback
private void sendSuccessEvent(String filepath) {
    if (successCallback != null) {
        HashMap event = new HashMap();
        event.put("filePath", filepath);
        event.put("fileName", outPutFileName);

        // Fire an event directly to the specified listener (callback)
        successCallback.call(getKrollObject(), event);
    }
}

// method to invoke error callback
private void sendErrorEvent(String message) {
    if (errorCallback != null) {
        HashMap event = new HashMap();
        event.put("message", message);

        // Fire an event directly to the specified listener (callback)
        errorCallback.call(getKrollObject(), event);
    }
}

// method to register callbacks, which all passed from javascript layer
@Kroll.method
public void registerCallbacks(HashMap args) {
    Object callback;

    // Save the callback functions, verifying that they are of the correct
    // type
    if (args.containsKey("success")) {
        callback = args.get("success");
        if (callback instanceof KrollFunction) {
            successCallback = (KrollFunction) callback;
        }
    }

    if (args.containsKey("error")) {
        callback = args.get("error");
        if (callback instanceof KrollFunction) {
            errorCallback = (KrollFunction) callback;
        }
    }
}

@Kroll.method
public void startRecording(HashMap args) {
    if (isRecording) {
        // calling sendErrorEvent to invoke error callback
        sendErrorEvent("Another audio record is inprogress");
    } else {
        recorder = null;
        // this method used to register success and error callbacks
        registerCallbacks(args);
        recorder = new MediaRecorder();

        recorder.setOutputFile(outputFileName);
        recorder.setOnErrorListener(errorListener);
        recorder.setOnInfoListener(infoListener);

        try {
            recorder.prepare();
            recorder.start();
            isRecording = true;
        } catch (IllegalStateException e) {
            System.out.println("@@## Error1 e = " + e);
            e.printStackTrace();
            isRecording = false;
            // calling sendErrorEvent to invoke error callback
            sendErrorEvent(e.toString());
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("@@## Error3 e = " + e);
            isRecording = false;
            // calling sendErrorEvent to invoke error callback
            sendErrorEvent(e.toString());
        }
    }
}
In Javascript
var audioRecorder = require("titutorial.audiorecorder");

audioRecorder.startRecording({
    outputFormat: audioRecorder.OutputFormat_THREE_GPP,
    audioEncoder: audioRecorder.AudioEncoder_AMR_NB,
    directoryName: "testdir",
    fileName: "testfile",
    maxFileSize: 7000,
    success: function (e) {
        alert("success => " + e.filePath);
    },
    error: function (d) {
        alert("error => " + e.message);
    }
});
For more detail refer AudioRecorder module source code and this blog post

Event listeners

Registered  event listeners will be called whenever the event occur.

Example


Lets consider Ratingbar module here when user change the rating, the new rating value passed  to javascript layer via event listener. It may fired so many times.

In Module
private boolean hasListenerChange = false;
//checks whether "change" event listener added to proxy or not
hasListenerChange = proxy.hasListeners("change");

ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
 @SuppressWarnings("deprecation")
 public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
  //if listener added to proxy, it pass the data to javascript layer
  if (hasListenerChange) {
   KrollDict props = new KrollDict();
   props.put("rating", rating);
   //fires the change event
   proxy.fireEvent("change", props);
  }
 }
});
In Javascript
var ratingbarProxy = require('titutorial.ratingbar');

var ratingBar = ratingbarProxy.createRatingBar({
    top : '30dp',
    left:15,
    rating : 2,
    stars : 6,
    stepSize : 1.5,
    isIndicator : false
});
win.add(ratingBar);

ratingBar.addEventListener('change', function(e) {
    ratingValue.text = "Rating Value : "+e.rating.toString();
});

For more detailed example refer Ratingbar module source code

Continue with part 3