{"id":292,"date":"2017-05-13T14:57:48","date_gmt":"2017-05-13T14:57:48","guid":{"rendered":"http:\/\/imalogic.com\/blog\/?p=292"},"modified":"2017-05-14T10:04:10","modified_gmt":"2017-05-14T10:04:10","slug":"writing-c-code-for-android","status":"publish","type":"post","link":"https:\/\/imalogic.com\/blog\/2017\/05\/13\/writing-c-code-for-android\/","title":{"rendered":"Writing \u201cC\u201d Code for Android"},"content":{"rendered":"<body><p><\/p>\n<h1><a href=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/ndk_droid.jpg?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"294\" data-permalink=\"https:\/\/imalogic.com\/blog\/2017\/05\/13\/writing-c-code-for-android\/ndk_droid\/\" data-orig-file=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/ndk_droid.jpg?fit=169%2C155&amp;ssl=1\" data-orig-size=\"169,155\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ndk_droid\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/ndk_droid.jpg?fit=169%2C155&amp;ssl=1\" class=\"size-full wp-image-294 alignright\" src=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/ndk_droid.jpg?resize=169%2C155&#038;ssl=1\" alt=\"\" width=\"169\" height=\"155\" loading=\"lazy\"><\/a>The Android SDK<\/h1>\n<p>The Android SDK is strictly for Java Programmers \u2014 however, the Native Development Kit cracks the door to let some \u201cC\u201d inside<\/p>\n<p>The supported and prescribed manner of creating Android applications is via the Android SDK and that means writing your applications in Java.<\/p>\n<p><strong>But what if you have a large body of code already written in C and you want to take leverage that investment for your Android efforts ?<\/strong> Should you port your code to Java ? Porting your code may be the right answer, but before you start refactoring your code into Java, you should have a look at the Android Native Development Kit (<strong>NDK)<\/strong>.<\/p>\n<p>Introduced around the release of Android version 1.5, the Android NDK permits developers to write code in \u201cC\u201d that is then callable from Android applications written in Java. The plumbing between the environments is known as the Java Native Interface, or JNI.<\/p>\n<p>JNI has been around for years as a means to permit Java developers to access vendor SDKs or other available C code. Early on, the majority of software vendors\u2019 SDKs were provided as C language static or dynamic libraries \u2014 however, this didn\u2019t do Java programmers much good.<\/p>\n<p>The solution to providing the functionality of those SDKs to Java applications was to write a \u201cwrapper\u201d dll in C. The wrapper implemented the Java Native Interface and then proxies calls to the third-party dll. Over time as Java became more popular, some thoughtful vendors began shipping their libraries Java-ready by providing their own JNI wrappers. Today Android developers can leverage C code with JNI with the help of the NDK.<\/p>\n<h1 class=\"subhead\"><\/h1>\n<h1 class=\"subhead\">Building a JNI app<\/h1>\n<p>We\u2019ll start by building our JNI C code, implementing the two methods of interest. Here is the C code.<\/p>\n<pre class=\"WonB\">#include &lt;string.h&gt;\r\n#include &lt;jni.h&gt;\r\n\r\njstring <strong>Java_com_msi_mymodule_jnisample_LMJNI_stringFromJNI(<\/strong> JNIEnv* env,\r\n                                                             jobject thiz )\r\n{\r\n    return (*env)-&gt;NewStringUTF(env, \"Hello from Imalogic !\");\r\n}\r\n\r\njint <strong>Java_com_msi_mymodule_jnisample_LMJNI_incrementFromJNI<\/strong>(JNIEnv* env,\r\n                                                            jobject thiz,\r\n                                                            jint innumber)\r\n{\r\n\treturn innumber + 1;\r\n}\r\n<\/pre>\n<p>The methods are named according to the following pattern:<\/p>\n<p>Java_&lt;the fully qualified Java name space with \u201c.\u201d replaced with \u201c_\u201d&gt;_methodname<\/p>\n<p>In our Java code shown below, the Java package name is com.msi.mymodule.jnisample and the class name is LMJNI. Therefore the function prefix is: \u201cJava_com_msi_mymodule_jnisample_LMJNI_\u201d<\/p>\n<p>Once the code is written, we also need a couple of Makefile snippets to grease the skids in the build process.<\/p>\n<p>In our Android Java application, the application has two TextView (edit box) fields and two buttons, organized into pairs. The first pair is used to exercise the \u201cget a string\u201d JNI function and the second is used for the \u201cincrement a number\u201d function.<\/p>\n<pre class=\"WonB\">package com.msi.mymodule.jnisample;\r\n\r\nimport android.app.Activity;\r\nimport android.os.Bundle;\r\nimport android.view.View;\r\nimport android.widget.TextView;\r\nimport android.widget.Button;\r\n\r\npublic class LMJNI extends Activity {\r\n    \/** Called when the activity is first created. *\/\r\n    @Override\r\n    public void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.main);\r\n\r\n        Button btnGetString = (Button) this.findViewById(R.id.btnGetString);\r\n        btnGetString.setOnClickListener(new Button.OnClickListener() {\r\n        \tpublic void onClick(View v) {\r\n\t                TextView label = (TextView) findViewById(R.id.TheLabel);\r\n\t               <span style=\"color: #339966;\"> label.setText(<strong>stringFromJNI()<\/strong>);   \/\/ calling a JNI function here!<\/span>\r\n        \t}\r\n        });\r\n\r\n        Button btnAddNumber = (Button) this.findViewById(R.id.btnAddNumber);\r\n        btnAddNumber.setOnClickListener(new Button.OnClickListener(){\r\n        \tpublic void onClick(View v) {\r\n\t                TextView numberField = (TextView) findViewById(R.id.number);\r\n\t                int operand = Integer.parseInt(numberField.getText().toString());\r\n\t               <span style=\"color: #339966;\"> int answer = <strong>incrementFromJNI<\/strong>(operand);  \/\/ calling a JNI function here!<\/span>\r\n\t                numberField.setText(\"\" + answer);\r\n        \t}\r\n        });\r\n    }\r\n\r\n   <strong> \/\/ declare the externally provided methods<\/strong>\r\n    public native String  <strong>stringFromJNI()<\/strong>;\r\n    public native int <span style=\"color: #339966;\"><strong>incrementFromJNI(int number)<\/strong><\/span>;\r\n\r\n    static {\r\n    \t<span style=\"color: #339966;\"><strong>\/\/ load our JNI library.  Note, leave off the \"lib\" and the \".so\"\r\n        System.loadLibrary(\"mymodule\");<\/strong><\/span>\r\n    }\r\n}<\/pre>\n<p>\u00a0<\/p>\n<\/body>","protected":false},"excerpt":{"rendered":"<p>The Android SDK The Android SDK is strictly for Java Programmers \u2014 however, the Native Development Kit cracks the door<\/p>\n","protected":false},"author":1,"featured_media":294,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[63,7],"tags":[],"class_list":["post-292","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-coding"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/ndk_droid.jpg?fit=169%2C155&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8J21V-4I","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/292","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/comments?post=292"}],"version-history":[{"count":1,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/292\/revisions"}],"predecessor-version":[{"id":335,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/292\/revisions\/335"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/media\/294"}],"wp:attachment":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/media?parent=292"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/categories?post=292"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/tags?post=292"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}