SlideShare a Scribd company logo
1 of 23
Download to read offline
Building Native Camera Access - Part II
Now that we have the generic code of the library lets go into the Android port
Android Port
© Codename One 2017 all rights reserved
✦Use the include source feature
✦You can implement and debug the code right within the
native IDE
✦This applies to both iOS & Android
If this is the first tutorial on building native interfaces you are going through then here's an important tip. Use the include source feature of Codename One and build an
Android Studio project. Then implement the native interface within Android Studio. You can then copy and paste the code back into the Codename One project.

This is far more convenient as you can implement and debug the code right within the native IDE. 

The same is true for xcode when working on a Mac. In this case because the native interface was so simple (albeit large) I skipped that stage but I have a bit of
experience doing this. Most of you would probably feel more comfortable building the hello world app with the native interface and implementing it in Android Studio.
import com.wonderkiln.camerakit.*;
import com.codename1.impl.android.AndroidNativeUtil;
import com.codename1.impl.android.AndroidImplementation;
import java.io.File;
CameraNativeAccessImpl
The Android port is trivial. Once we have the native interface we can right click the project and choose "Generate Native Stubs" which produces the skeleton code for
this implementation class. 

Unlike before I'll start with the imports as some of them are a bit challenging.

I just imported everything as it was simpler
import com.wonderkiln.camerakit.*;
import com.codename1.impl.android.AndroidNativeUtil;
import com.codename1.impl.android.AndroidImplementation;
import java.io.File;
CameraNativeAccessImpl
This is an important helper class when writing native Android code, you will see me use it soon
import com.wonderkiln.camerakit.*;
import com.codename1.impl.android.AndroidNativeUtil;
import com.codename1.impl.android.AndroidImplementation;
import java.io.File;
CameraNativeAccessImpl
I wanted one method from the implementation: runOnUiThreadAndWait. It's really useful in some cases
public class CameraNativeAccessImpl {
private CameraView view;
private CameraKitEventListener listener =
new CameraKitEventListener() {
public void onEvent(CameraKitEvent event) {}
public void onError(CameraKitError error) {
String errorMessage = "";
if(error.getException() != null) {
errorMessage = error.getException().toString();
com.codename1.io.Log.e(error.getException());
com.codename1.io.Log.sendLogAsync();
}
CameraCallbacks.onError(error.getType(),
error.getMessage(), errorMessage);
}
public void onImage(CameraKitImage image) {
CameraCallbacks.onImage(image.getJpeg());
}
public void onVideo(CameraKitVideo video) {
CameraCallbacks.onVideo("file://" +
video.getVideoFile().getAbsolutePath());
}
};
CameraNativeAccessImpl
Lets get into the code itself. 

The view is the camera preview UI, I keep it as a member to return later.
public class CameraNativeAccessImpl {
private CameraView view;
private CameraKitEventListener listener =
new CameraKitEventListener() {
public void onEvent(CameraKitEvent event) {}
public void onError(CameraKitError error) {
String errorMessage = "";
if(error.getException() != null) {
errorMessage = error.getException().toString();
com.codename1.io.Log.e(error.getException());
com.codename1.io.Log.sendLogAsync();
}
CameraCallbacks.onError(error.getType(),
error.getMessage(), errorMessage);
}
public void onImage(CameraKitImage image) {
CameraCallbacks.onImage(image.getJpeg());
}
public void onVideo(CameraKitVideo video) {
CameraCallbacks.onVideo("file://" +
video.getVideoFile().getAbsolutePath());
}
};
CameraNativeAccessImpl
The listener is bound later in the code, it just delegates all the calls into the callback. Notice I have only one listener on the native side.

All calls are effectively the same they just invoke the `CameraCallbacks` class methods
public class CameraNativeAccessImpl {
private CameraView view;
private CameraKitEventListener listener =
new CameraKitEventListener() {
public void onEvent(CameraKitEvent event) {}
public void onError(CameraKitError error) {
String errorMessage = "";
if(error.getException() != null) {
errorMessage = error.getException().toString();
com.codename1.io.Log.e(error.getException());
com.codename1.io.Log.sendLogAsync();
}
CameraCallbacks.onError(error.getType(),
error.getMessage(), errorMessage);
}
public void onImage(CameraKitImage image) {
CameraCallbacks.onImage(image.getJpeg());
}
public void onVideo(CameraKitVideo video) {
CameraCallbacks.onVideo("file://" +
video.getVideoFile().getAbsolutePath());
}
};
CameraNativeAccessImpl
Android native file paths should be prepended with file:// to work in Codename One's FileSystemStorage.
public void start() {
AndroidImplementation.runOnUiThreadAndBlock(new Runnable() {
public void run() {
if(view == null) {
view = new CameraView(AndroidNativeUtil.getContext());
view.addCameraKitListener(listener);
}
view.start();
}
});
}
public void stop() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.stop();
}
});
}
public boolean isStarted() {
if(view == null) {
return false;
}
return view.isStarted();
}
CameraNativeAccessImpl
The next step is lifecycle and view methods. After the start method is invoked I'd like the view object to be valid otherwise we might have a problem. This code MUST run
on Androids native EDT hence the need for runOnUiThreadAndBlock()
public void start() {
AndroidImplementation.runOnUiThreadAndBlock(new Runnable() {
public void run() {
if(view == null) {
view = new CameraView(AndroidNativeUtil.getContext());
view.addCameraKitListener(listener);
}
view.start();
}
});
}
public void stop() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.stop();
}
});
}
public boolean isStarted() {
if(view == null) {
return false;
}
return view.isStarted();
}
CameraNativeAccessImpl
We initialize the view, bind the listener and start(). Notice we can start & stop() more than once
public void start() {
AndroidImplementation.runOnUiThreadAndBlock(new Runnable() {
public void run() {
if(view == null) {
view = new CameraView(AndroidNativeUtil.getContext());
view.addCameraKitListener(listener);
}
view.start();
}
});
}
public void stop() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.stop();
}
});
}
public boolean isStarted() {
if(view == null) {
return false;
}
return view.isStarted();
}
CameraNativeAccessImpl
We don't need to "wait" for stop() to complete but it still needs to run on Android's dispatch thread
public void run() {
view.stop();
}
});
}
public boolean isStarted() {
if(view == null) {
return false;
}
return view.isStarted();
}
public void setMethod(final int param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.setMethod(param);
}
});
}
public android.view.View getView() {
return view;
}
public boolean isSupported() {
return true;
}
CameraNativeAccessImpl
This method returns a PeerComponent in the Java side. The Android view is translated automatically
public void run() {
view.stop();
}
});
}
public boolean isStarted() {
if(view == null) {
return false;
}
return view.isStarted();
}
public void setMethod(final int param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.setMethod(param);
}
});
}
public android.view.View getView() {
return view;
}
public boolean isSupported() {
return true;
}
CameraNativeAccessImpl
The isSupported method is a standard method in native interfaces which defaults to false. When you implement a version in a platform set it to true
public void setPermissions(final int param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.setPermissions(param);
}
});
}
public void setZoom(final float param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.setZoom(param);
}
});
}
public void setFocus(final int param) {
// ... same runOnUiThread code
}
public void setFlash(final int param) {
// ... same runOnUiThread code
}
public void setFacing(final int param) {
// ... same runOnUiThread code
}
CameraNativeAccessImpl
Next lets do a quick recap of the setter methods in the native interface. We can't use a Lambda yet because we are still using Java 5 for Android native code. This might
change by the time you see this!

We hope to upgrade Android native code for newer builds to use Java 8 syntax which will shorten the boilerplate here significantly.
public void setPermissions(final int param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.setPermissions(param);
}
});
}
public void setZoom(final float param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.setZoom(param);
}
});
}
public void setFocus(final int param) {
// ... same runOnUiThread code
}
public void setFlash(final int param) {
// ... same runOnUiThread code
}
public void setFacing(final int param) {
// ... same runOnUiThread code
}
CameraNativeAccessImpl
All of the methods here work roughly in the same way by delegating to the native call via the runOnUiThread call.

I could go for a couple of additional pages of setters but you get the drift, it’s more of the same…
public int getFacing() {
return view.getFacing();
}
public boolean isFacingFront() {
return view.isFacingFront();
}
public boolean isFacingBack() {
return view.isFacingBack();
}
public float getVerticalViewingAngle() {
return view.getCameraProperties().verticalViewingAngle;
}
public float getHorizontalViewingAngle() {
return view.getCameraProperties().horizontalViewingAngle;
}
public int getFlash() {
return view.getFlash();
}
public int getPreviewWidth() {
return view.getPreviewSize().getWidth();
}
public int getPreviewHeight() {
return view.getPreviewSize().getHeight();
CameraNativeAccessImpl
Next we can review the getters which are shorter. Notice we don't need to use runOnUiThread as the getters aren't as sensitive to threading
public int getFacing() {
return view.getFacing();
}
public boolean isFacingFront() {
return view.isFacingFront();
}
public boolean isFacingBack() {
return view.isFacingBack();
}
public float getVerticalViewingAngle() {
return view.getCameraProperties().verticalViewingAngle;
}
public float getHorizontalViewingAngle() {
return view.getCameraProperties().horizontalViewingAngle;
}
public int getFlash() {
return view.getFlash();
}
public int getPreviewWidth() {
return view.getPreviewSize().getWidth();
}
public int getPreviewHeight() {
return view.getPreviewSize().getHeight();
CameraNativeAccessImpl
As you may recall some of the methods here map to properties of the returned objects as is the case here and with the preview/capture methods below. 

Like the setters this goes on a bit further so I’ll spare you an additional slide where I don’t have anything interesting to say…
public void captureVideoFile(final String param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
String f = param;
if (param.startsWith("file://")) {
f = param.substring(7);
}
view.captureVideo(new File(f));
}
});
}
public void captureImage() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.captureImage();
}
});
}
public void captureVideo() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.captureVideo();
}
});
}
public void stopVideo() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
CameraNativeAccessImpl
Finally we have the capture method calls. We need runOnUiThread as capture is thread sensitive
public void captureVideoFile(final String param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
String f = param;
if (param.startsWith("file://")) {
f = param.substring(7);
}
view.captureVideo(new File(f));
}
});
}
public void captureImage() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.captureImage();
}
});
}
public void captureVideo() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.captureVideo();
}
});
}
public void stopVideo() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
CameraNativeAccessImpl
Files in Codename One have file URL prepended so they will act as URL's we remove this to translate the file into an Android file.
public void captureVideoFile(final String param) {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
String f = param;
if (param.startsWith("file://")) {
f = param.substring(7);
}
view.captureVideo(new File(f));
}
});
}
public void captureImage() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.captureImage();
}
});
}
public void captureVideo() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
public void run() {
view.captureVideo();
}
});
}
public void stopVideo() {
AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() {
CameraNativeAccessImpl
All the other methods are exactly the same. They just invoke the native Android version. This is it for the code but it won't work yet…
Build Hints
© Codename One 2017 all rights reserved
android.gradleDep=compile 'com.wonderkiln:camerakit:0.13.1';
We need three build hints to get this to work. The camera kit page asks that we add the gradle build dependency. The Codename one equivalent of that is the build hint
android.gradleDep
ProGuard
© Codename One 2017 all rights reserved
android.proguardKeep=-dontwarn com.google.android.gms.**
The page also mentions a proguard entry (a bit down in the page). This is handled by the android.proguardKeep build hint
Build Tools 27
© Codename One 2017 all rights reserved
android.buildToolsVersion=27
Unfortunately if you go through all of that things still won't compile because of the old build tools version and target so we need to use the latest version of build tools
which camera kit depends on. Specifically android.buildToolsVersion=27.

This line is a temporary fix, we will soon flip the default build tools version to 27 at which point it will be redundant. Once this is done we recommend removing it so when
we go to 28 it will use that.

Once all of this is done you should be able to use Camera Kit on Android. The challenge is now iOS…

More Related Content

Similar to Building a Native Camera Access Library - Part II - Transcript.pdf

[Ultracode Munich #4] Short introduction to the new Android build system incl...
[Ultracode Munich #4] Short introduction to the new Android build system incl...[Ultracode Munich #4] Short introduction to the new Android build system incl...
[Ultracode Munich #4] Short introduction to the new Android build system incl...BeMyApp
 
How React Native, Appium and me made each other shine @Frontmania 16-11-2018
How React Native, Appium and me made each other shine @Frontmania 16-11-2018How React Native, Appium and me made each other shine @Frontmania 16-11-2018
How React Native, Appium and me made each other shine @Frontmania 16-11-2018Wim Selles
 
Inside Android's UI at AnDevCon VI
Inside Android's UI at AnDevCon VIInside Android's UI at AnDevCon VI
Inside Android's UI at AnDevCon VIOpersys inc.
 
Setting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with AppiumSetting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with Appiummobiletestsummit
 
Inside Android's UI at AnDevCon V
Inside Android's UI at AnDevCon VInside Android's UI at AnDevCon V
Inside Android's UI at AnDevCon VOpersys inc.
 
Mastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin EdelsonMastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin EdelsonAEM HUB
 
Mastering the Sling Rewriter
Mastering the Sling RewriterMastering the Sling Rewriter
Mastering the Sling RewriterJustin Edelson
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Controlbhochhi
 
Android, the life of your app
Android, the life of your appAndroid, the life of your app
Android, the life of your appEyal Lezmy
 
DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...
DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...
DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...Olivier Destrebecq
 
Building a Native Camera Access Library - Part V - Transcript.pdf
Building a Native Camera Access Library - Part V - Transcript.pdfBuilding a Native Camera Access Library - Part V - Transcript.pdf
Building a Native Camera Access Library - Part V - Transcript.pdfShaiAlmog1
 
Android Studio App that lets you upload pictures to the app.Hello,.pdf
Android Studio App that lets you upload pictures to the app.Hello,.pdfAndroid Studio App that lets you upload pictures to the app.Hello,.pdf
Android Studio App that lets you upload pictures to the app.Hello,.pdffeelingcomputors
 
Cross-platform mobile apps with Apache Cordova
Cross-platform mobile apps with Apache CordovaCross-platform mobile apps with Apache Cordova
Cross-platform mobile apps with Apache CordovaIvano Malavolta
 
Building a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdfBuilding a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdfShaiAlmog1
 
Android UI Testing with Appium
Android UI Testing with AppiumAndroid UI Testing with Appium
Android UI Testing with AppiumLuke Maung
 
Session2-J2ME development-environment
Session2-J2ME development-environmentSession2-J2ME development-environment
Session2-J2ME development-environmentmuthusvm
 

Similar to Building a Native Camera Access Library - Part II - Transcript.pdf (20)

[Ultracode Munich #4] Short introduction to the new Android build system incl...
[Ultracode Munich #4] Short introduction to the new Android build system incl...[Ultracode Munich #4] Short introduction to the new Android build system incl...
[Ultracode Munich #4] Short introduction to the new Android build system incl...
 
How React Native, Appium and me made each other shine @Frontmania 16-11-2018
How React Native, Appium and me made each other shine @Frontmania 16-11-2018How React Native, Appium and me made each other shine @Frontmania 16-11-2018
How React Native, Appium and me made each other shine @Frontmania 16-11-2018
 
Inside Android's UI at AnDevCon VI
Inside Android's UI at AnDevCon VIInside Android's UI at AnDevCon VI
Inside Android's UI at AnDevCon VI
 
Setting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with AppiumSetting Apple's UI Automation Free with Appium
Setting Apple's UI Automation Free with Appium
 
Inside Android's UI at AnDevCon V
Inside Android's UI at AnDevCon VInside Android's UI at AnDevCon V
Inside Android's UI at AnDevCon V
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Mastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin EdelsonMastering the Sling Rewriter by Justin Edelson
Mastering the Sling Rewriter by Justin Edelson
 
Mastering the Sling Rewriter
Mastering the Sling RewriterMastering the Sling Rewriter
Mastering the Sling Rewriter
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
Di code steps
Di code stepsDi code steps
Di code steps
 
Lightning Talk - Xamarin
Lightning Talk - Xamarin Lightning Talk - Xamarin
Lightning Talk - Xamarin
 
Android, the life of your app
Android, the life of your appAndroid, the life of your app
Android, the life of your app
 
DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...
DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...
DMCA #25: Jenkins - Docker & Android: Comment Docker peu faciliter la créatio...
 
Building a Native Camera Access Library - Part V - Transcript.pdf
Building a Native Camera Access Library - Part V - Transcript.pdfBuilding a Native Camera Access Library - Part V - Transcript.pdf
Building a Native Camera Access Library - Part V - Transcript.pdf
 
Android Studio App that lets you upload pictures to the app.Hello,.pdf
Android Studio App that lets you upload pictures to the app.Hello,.pdfAndroid Studio App that lets you upload pictures to the app.Hello,.pdf
Android Studio App that lets you upload pictures to the app.Hello,.pdf
 
Camera
CameraCamera
Camera
 
Cross-platform mobile apps with Apache Cordova
Cross-platform mobile apps with Apache CordovaCross-platform mobile apps with Apache Cordova
Cross-platform mobile apps with Apache Cordova
 
Building a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdfBuilding a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdf
 
Android UI Testing with Appium
Android UI Testing with AppiumAndroid UI Testing with Appium
Android UI Testing with Appium
 
Session2-J2ME development-environment
Session2-J2ME development-environmentSession2-J2ME development-environment
Session2-J2ME development-environment
 

More from ShaiAlmog1

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...ShaiAlmog1
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfShaiAlmog1
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfShaiAlmog1
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfShaiAlmog1
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfShaiAlmog1
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfShaiAlmog1
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfShaiAlmog1
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfShaiAlmog1
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfShaiAlmog1
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfShaiAlmog1
 

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 

Recently uploaded

Oauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftOauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftshyamraj55
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAnitaRaj43
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctBrainSell Technologies
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMKumar Satyam
 
Generative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfGenerative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfalexjohnson7307
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceSamy Fodil
 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxFIDO Alliance
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard37
 
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)Paige Cruz
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsLeah Henrickson
 
الأمن السيبراني - ما لا يسع للمستخدم جهله
الأمن السيبراني - ما لا يسع للمستخدم جهلهالأمن السيبراني - ما لا يسع للمستخدم جهله
الأمن السيبراني - ما لا يسع للمستخدم جهلهMohamed Sweelam
 
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...marcuskenyatta275
 
State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!Memoori
 
JavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuideJavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuidePixlogix Infotech
 
Introduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxIntroduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxFIDO Alliance
 
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfFrisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfAnubhavMangla3
 
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...panagenda
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxFIDO Alliance
 

Recently uploaded (20)

Oauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftOauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoft
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage Intacct
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
Generative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfGenerative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdf
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
Overview of Hyperledger Foundation
Overview of Hyperledger FoundationOverview of Hyperledger Foundation
Overview of Hyperledger Foundation
 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
Observability Concepts EVERY Developer Should Know (DevOpsDays Seattle)
 
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
 
الأمن السيبراني - ما لا يسع للمستخدم جهله
الأمن السيبراني - ما لا يسع للمستخدم جهلهالأمن السيبراني - ما لا يسع للمستخدم جهله
الأمن السيبراني - ما لا يسع للمستخدم جهله
 
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
 
State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!State of the Smart Building Startup Landscape 2024!
State of the Smart Building Startup Landscape 2024!
 
JavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuideJavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate Guide
 
Introduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxIntroduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptx
 
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfFrisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
 
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
Easier, Faster, and More Powerful – Alles Neu macht der Mai -Wir durchleuchte...
 
ADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptxADP Passwordless Journey Case Study.pptx
ADP Passwordless Journey Case Study.pptx
 

Building a Native Camera Access Library - Part II - Transcript.pdf

  • 1. Building Native Camera Access - Part II Now that we have the generic code of the library lets go into the Android port
  • 2. Android Port © Codename One 2017 all rights reserved ✦Use the include source feature ✦You can implement and debug the code right within the native IDE ✦This applies to both iOS & Android If this is the first tutorial on building native interfaces you are going through then here's an important tip. Use the include source feature of Codename One and build an Android Studio project. Then implement the native interface within Android Studio. You can then copy and paste the code back into the Codename One project. This is far more convenient as you can implement and debug the code right within the native IDE. The same is true for xcode when working on a Mac. In this case because the native interface was so simple (albeit large) I skipped that stage but I have a bit of experience doing this. Most of you would probably feel more comfortable building the hello world app with the native interface and implementing it in Android Studio.
  • 3. import com.wonderkiln.camerakit.*; import com.codename1.impl.android.AndroidNativeUtil; import com.codename1.impl.android.AndroidImplementation; import java.io.File; CameraNativeAccessImpl The Android port is trivial. Once we have the native interface we can right click the project and choose "Generate Native Stubs" which produces the skeleton code for this implementation class. Unlike before I'll start with the imports as some of them are a bit challenging. I just imported everything as it was simpler
  • 4. import com.wonderkiln.camerakit.*; import com.codename1.impl.android.AndroidNativeUtil; import com.codename1.impl.android.AndroidImplementation; import java.io.File; CameraNativeAccessImpl This is an important helper class when writing native Android code, you will see me use it soon
  • 5. import com.wonderkiln.camerakit.*; import com.codename1.impl.android.AndroidNativeUtil; import com.codename1.impl.android.AndroidImplementation; import java.io.File; CameraNativeAccessImpl I wanted one method from the implementation: runOnUiThreadAndWait. It's really useful in some cases
  • 6. public class CameraNativeAccessImpl { private CameraView view; private CameraKitEventListener listener = new CameraKitEventListener() { public void onEvent(CameraKitEvent event) {} public void onError(CameraKitError error) { String errorMessage = ""; if(error.getException() != null) { errorMessage = error.getException().toString(); com.codename1.io.Log.e(error.getException()); com.codename1.io.Log.sendLogAsync(); } CameraCallbacks.onError(error.getType(), error.getMessage(), errorMessage); } public void onImage(CameraKitImage image) { CameraCallbacks.onImage(image.getJpeg()); } public void onVideo(CameraKitVideo video) { CameraCallbacks.onVideo("file://" + video.getVideoFile().getAbsolutePath()); } }; CameraNativeAccessImpl Lets get into the code itself. The view is the camera preview UI, I keep it as a member to return later.
  • 7. public class CameraNativeAccessImpl { private CameraView view; private CameraKitEventListener listener = new CameraKitEventListener() { public void onEvent(CameraKitEvent event) {} public void onError(CameraKitError error) { String errorMessage = ""; if(error.getException() != null) { errorMessage = error.getException().toString(); com.codename1.io.Log.e(error.getException()); com.codename1.io.Log.sendLogAsync(); } CameraCallbacks.onError(error.getType(), error.getMessage(), errorMessage); } public void onImage(CameraKitImage image) { CameraCallbacks.onImage(image.getJpeg()); } public void onVideo(CameraKitVideo video) { CameraCallbacks.onVideo("file://" + video.getVideoFile().getAbsolutePath()); } }; CameraNativeAccessImpl The listener is bound later in the code, it just delegates all the calls into the callback. Notice I have only one listener on the native side. All calls are effectively the same they just invoke the `CameraCallbacks` class methods
  • 8. public class CameraNativeAccessImpl { private CameraView view; private CameraKitEventListener listener = new CameraKitEventListener() { public void onEvent(CameraKitEvent event) {} public void onError(CameraKitError error) { String errorMessage = ""; if(error.getException() != null) { errorMessage = error.getException().toString(); com.codename1.io.Log.e(error.getException()); com.codename1.io.Log.sendLogAsync(); } CameraCallbacks.onError(error.getType(), error.getMessage(), errorMessage); } public void onImage(CameraKitImage image) { CameraCallbacks.onImage(image.getJpeg()); } public void onVideo(CameraKitVideo video) { CameraCallbacks.onVideo("file://" + video.getVideoFile().getAbsolutePath()); } }; CameraNativeAccessImpl Android native file paths should be prepended with file:// to work in Codename One's FileSystemStorage.
  • 9. public void start() { AndroidImplementation.runOnUiThreadAndBlock(new Runnable() { public void run() { if(view == null) { view = new CameraView(AndroidNativeUtil.getContext()); view.addCameraKitListener(listener); } view.start(); } }); } public void stop() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.stop(); } }); } public boolean isStarted() { if(view == null) { return false; } return view.isStarted(); } CameraNativeAccessImpl The next step is lifecycle and view methods. After the start method is invoked I'd like the view object to be valid otherwise we might have a problem. This code MUST run on Androids native EDT hence the need for runOnUiThreadAndBlock()
  • 10. public void start() { AndroidImplementation.runOnUiThreadAndBlock(new Runnable() { public void run() { if(view == null) { view = new CameraView(AndroidNativeUtil.getContext()); view.addCameraKitListener(listener); } view.start(); } }); } public void stop() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.stop(); } }); } public boolean isStarted() { if(view == null) { return false; } return view.isStarted(); } CameraNativeAccessImpl We initialize the view, bind the listener and start(). Notice we can start & stop() more than once
  • 11. public void start() { AndroidImplementation.runOnUiThreadAndBlock(new Runnable() { public void run() { if(view == null) { view = new CameraView(AndroidNativeUtil.getContext()); view.addCameraKitListener(listener); } view.start(); } }); } public void stop() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.stop(); } }); } public boolean isStarted() { if(view == null) { return false; } return view.isStarted(); } CameraNativeAccessImpl We don't need to "wait" for stop() to complete but it still needs to run on Android's dispatch thread
  • 12. public void run() { view.stop(); } }); } public boolean isStarted() { if(view == null) { return false; } return view.isStarted(); } public void setMethod(final int param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.setMethod(param); } }); } public android.view.View getView() { return view; } public boolean isSupported() { return true; } CameraNativeAccessImpl This method returns a PeerComponent in the Java side. The Android view is translated automatically
  • 13. public void run() { view.stop(); } }); } public boolean isStarted() { if(view == null) { return false; } return view.isStarted(); } public void setMethod(final int param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.setMethod(param); } }); } public android.view.View getView() { return view; } public boolean isSupported() { return true; } CameraNativeAccessImpl The isSupported method is a standard method in native interfaces which defaults to false. When you implement a version in a platform set it to true
  • 14. public void setPermissions(final int param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.setPermissions(param); } }); } public void setZoom(final float param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.setZoom(param); } }); } public void setFocus(final int param) { // ... same runOnUiThread code } public void setFlash(final int param) { // ... same runOnUiThread code } public void setFacing(final int param) { // ... same runOnUiThread code } CameraNativeAccessImpl Next lets do a quick recap of the setter methods in the native interface. We can't use a Lambda yet because we are still using Java 5 for Android native code. This might change by the time you see this! We hope to upgrade Android native code for newer builds to use Java 8 syntax which will shorten the boilerplate here significantly.
  • 15. public void setPermissions(final int param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.setPermissions(param); } }); } public void setZoom(final float param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.setZoom(param); } }); } public void setFocus(final int param) { // ... same runOnUiThread code } public void setFlash(final int param) { // ... same runOnUiThread code } public void setFacing(final int param) { // ... same runOnUiThread code } CameraNativeAccessImpl All of the methods here work roughly in the same way by delegating to the native call via the runOnUiThread call. I could go for a couple of additional pages of setters but you get the drift, it’s more of the same…
  • 16. public int getFacing() { return view.getFacing(); } public boolean isFacingFront() { return view.isFacingFront(); } public boolean isFacingBack() { return view.isFacingBack(); } public float getVerticalViewingAngle() { return view.getCameraProperties().verticalViewingAngle; } public float getHorizontalViewingAngle() { return view.getCameraProperties().horizontalViewingAngle; } public int getFlash() { return view.getFlash(); } public int getPreviewWidth() { return view.getPreviewSize().getWidth(); } public int getPreviewHeight() { return view.getPreviewSize().getHeight(); CameraNativeAccessImpl Next we can review the getters which are shorter. Notice we don't need to use runOnUiThread as the getters aren't as sensitive to threading
  • 17. public int getFacing() { return view.getFacing(); } public boolean isFacingFront() { return view.isFacingFront(); } public boolean isFacingBack() { return view.isFacingBack(); } public float getVerticalViewingAngle() { return view.getCameraProperties().verticalViewingAngle; } public float getHorizontalViewingAngle() { return view.getCameraProperties().horizontalViewingAngle; } public int getFlash() { return view.getFlash(); } public int getPreviewWidth() { return view.getPreviewSize().getWidth(); } public int getPreviewHeight() { return view.getPreviewSize().getHeight(); CameraNativeAccessImpl As you may recall some of the methods here map to properties of the returned objects as is the case here and with the preview/capture methods below. Like the setters this goes on a bit further so I’ll spare you an additional slide where I don’t have anything interesting to say…
  • 18. public void captureVideoFile(final String param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { String f = param; if (param.startsWith("file://")) { f = param.substring(7); } view.captureVideo(new File(f)); } }); } public void captureImage() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.captureImage(); } }); } public void captureVideo() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.captureVideo(); } }); } public void stopVideo() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { CameraNativeAccessImpl Finally we have the capture method calls. We need runOnUiThread as capture is thread sensitive
  • 19. public void captureVideoFile(final String param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { String f = param; if (param.startsWith("file://")) { f = param.substring(7); } view.captureVideo(new File(f)); } }); } public void captureImage() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.captureImage(); } }); } public void captureVideo() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.captureVideo(); } }); } public void stopVideo() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { CameraNativeAccessImpl Files in Codename One have file URL prepended so they will act as URL's we remove this to translate the file into an Android file.
  • 20. public void captureVideoFile(final String param) { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { String f = param; if (param.startsWith("file://")) { f = param.substring(7); } view.captureVideo(new File(f)); } }); } public void captureImage() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.captureImage(); } }); } public void captureVideo() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { public void run() { view.captureVideo(); } }); } public void stopVideo() { AndroidNativeUtil.getActivity().runOnUiThread(new Runnable() { CameraNativeAccessImpl All the other methods are exactly the same. They just invoke the native Android version. This is it for the code but it won't work yet…
  • 21. Build Hints © Codename One 2017 all rights reserved android.gradleDep=compile 'com.wonderkiln:camerakit:0.13.1'; We need three build hints to get this to work. The camera kit page asks that we add the gradle build dependency. The Codename one equivalent of that is the build hint android.gradleDep
  • 22. ProGuard © Codename One 2017 all rights reserved android.proguardKeep=-dontwarn com.google.android.gms.** The page also mentions a proguard entry (a bit down in the page). This is handled by the android.proguardKeep build hint
  • 23. Build Tools 27 © Codename One 2017 all rights reserved android.buildToolsVersion=27 Unfortunately if you go through all of that things still won't compile because of the old build tools version and target so we need to use the latest version of build tools which camera kit depends on. Specifically android.buildToolsVersion=27. This line is a temporary fix, we will soon flip the default build tools version to 27 at which point it will be redundant. Once this is done we recommend removing it so when we go to 28 it will use that. Once all of this is done you should be able to use Camera Kit on Android. The challenge is now iOS…