Had a normal c code that prints helloworld
#include<stdio.h>
int main(void)
{
printf("Helloworld");
return 0;
}
I have to make an app to run this c code on a device running in android without using NDK and JNU for this and output should be in text view .As i am new to android help me regarding this.
Related
I cross-compiled my C application for Android ARM with arm-linux-gnueabi tool under Ubuntu 16.04 LTS. I compiled it with static linking flag. This C application is big and it has complicated makefile. It compiled successfully without any errors. But it behaves differently on Android phone and Ubuntu PC. More precisely i have two problems:
popen() and system() functions don't work on Android. They are carried out but do nothing and don't give any errors. This problem i solved with dirty hack.
fgets() functions works strange on Android.
1. About first problem.
I did small research and found that Android doesn't use ordinary libc library (glibc or another library which implements POSIX standard properly). It uses Bionic library instead of it (sorry, Android is new OS for me). I looked into popen() and system() functions code and noticed that these functions use _PATH_BSHELL macros. _PATH_BSHELL is path to the actual system shell. This path is "/system/bin/sh" on Android and "/bin/sh" on Ubuntu.
When i understood it i tried to hook popen() and system() functions. I copied code of these functions from the Bionic source, than i defined macros #define _MY_PATH_BSHELL "/system/bin/sh" and replaced calls like execve(_MY_PATH_BSHELL, argp, environ); by execve(_MY_PATH_BSHELL, argp, environ); calls. So it started work properly.
2. About second problem.
On Ubuntu this code works properly:
is_received = false;
while(!is_received) {
FILE *cmd = popen(command, "r");
is_received = fgets(buf, sizeof(buf), cmd) == NULL ? false : true;
}
But on Android fgets() always returns NULL and this loop works infinitely long. I tried to use read() function instead of fgets() and it worked.
On Android this code with read() works properly:
is_received = false;
while(!is_received) {
FILE *cmd = hooked_popen(command, "r");
int fd = fileno(cmd);
is_received = read(fd, buf, sizeof(buf)) == 0 ? false : true;
}
My questions.
How to solve my problems with popen() and system() neatly and correctly? I think i have to link statically with Bionic library. Is it right? How can i do it in console without Android Studio? I read that it is necessary to use NDK but it is not clear to me how.
Why fgets() behavior isn't similar on Android and Ubuntu?
I've created a Qt dynamic lib that uses Qt SQL to open an SQLite database, but I'm getting this error:
QSqlDatabase: QSQLITE driver not loaded
QSqlDatabase: available drivers:
The DLL was working fine as part of a Qt Android application, however I need to use it through JNI from an existing Java application developed in Eclipse.
This is the shortest example code that reproduces the problem. I load the library from Java and call its init() method:
System.loadLibrary("plugins_sqldrivers_libqsqlite");
System.loadLibrary("Qt5Sql");
System.loadLibrary("MyQtLib");
MyQtLib.init();
And inside the Qt library I just call QSqlDatabase::addDatabase():
JNIEXPORT void JNICALL Java_test_MyQtLib_foo(JNIEnv *, jclass)
{
// Manually create a QCoreApplication instance.
int argc = 1;
static char arg[] = "";
static char *arg2 = arg;
app = new QCoreApplication(argc, &arg2);
// Try to add an SQLite db connection.
QSqlDatabase::addDatabase("QSQLITE");
}
Since the error is QSQLITE driver not loaded, and the Qt library was working inside a Qt application, I assume that Qt is doing some initialization that I'm missing.
But this didn't remove the error, so it must be something else. Normally, the Qt application will use QtApplication.java and QtActivity.java to perform some initialization, so they must be doing something more there that I'm not doing.
Eventually I stepped into the Qt sources to see how the SQLITE plugin is loaded (for the desktop build at least).
The relevant function was QFactoryLoader::update(). In it I noticed that it iterates all the directories in QCoreApplication::libraryPaths():
QStringList paths = QCoreApplication::libraryPaths();
for (int i = 0; i < paths.count(); ++i) {
If any of them has a sub-directory named "sqldrivers", it goes inside it and tries to load all the dynamic libraries in that sub-directory.
I then printed out the library paths in a test project I ran directly from Qt Creator - qDebug() << a.libraryPaths();, and I saw this path - /data/data/org.qtproject.example.untitled/qt-reserved-files/plugins. In this directory on my android phone there was a subdirectory named sqldrivers, that contained a single file - libqsqlite.so.
I then checked the .java files, and indeed QtActivity::startApp() adds the library path:
boolean bundlingQtLibs = false;
if (m_activityInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
&& m_activityInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
localPrefix = getApplicationInfo().dataDir + "/";
pluginsPrefix = localPrefix + "qt-reserved-files/";
cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
extractBundledPluginsAndImports(pluginsPrefix);
bundlingQtLibs = true;
}
The solution then would be to ensure that there is a sqldrivers/libqsqlite.so somewhere on the phone, and then add the parent folder of sqldrivers to the library path using QCoreApplication::addLibraryPath().
This question already has answers here:
How do I build a native (command line) executable to run on Android?
(4 answers)
Closed 9 years ago.
I don't know if that's even possible, but suppose I want to run a Hello World ANSI C program, how do I go about compiling, deploying and running it? Is it even possible?
Here's the example code of the program I have in mind:
#include <stdio.h>
int main(void)
{
FILE *f = fopen("/storage/sdcard0/download/hello_android.txt", "w");
if (f) {
fprintf(f, "File created by an ANSI C program.");
fclose(f);
}
return 0;
}
As you can see, it should create a file as "proof" that it has run successfully.
1. Compiling
You just have to known your hardware architecture, find the correct toolchain and cross-compil it with the static option. If you don't want to use the static option you have to link your binary to bionic and not libc. It means that you have to compile android from scratch, which will compile bionic. Then you could add your C files into the "android environement", create a Android.mk file and run mm.
2. Deploying
You have to use adb to push your binary to your phone. Something like:
adb push mybinary /data/
3. Running
Launch a shell using adb shell and simply run:
$ /data/mybinary
NOTE: To do step 2 and 3 your phone must be rooted
With the new 2.3rc version of OpenCV, we are able to run executables that use OpenCV in adb shell without dealing with JNI interfaces for android. The new version also comes with prebuilt native camera support. (see http://opencv.willowgarage.com/wiki/Android2.3.0 for details ) I would like to know if it is possible to capture a preview frame from the camera using an executable that runs run in adb shell. Using the code snippet in the documentation I wrote the following simple code:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
const char* message = "Capture a frame!";
const char* errorMessage = "Could not open the camera!";
int main(int argc, char* argv[])
{
// print message to console
printf("%s\n", message);
cv::VideoCapture capture(CV_CAP_ANDROID + 0);
//cv::VideoCapture capture(CV_CAP_ANDROID + 1);//front camera for Android 2.3.3 or newer
if( !capture.isOpened() )
{
printf("%s\n", errorMessage);
return 0;
}
capture.set(CV_CAP_PROP_FRAME_WIDTH, 640);
capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
cv::Mat frame;
capture >> frame;
if( !frame.empty() ){
imwrite("/mnt/sdcard/CaptureFrame.png", frame);
}
return 0;
}
(The build scripts are similar to HelloAndroid sample application in the downloaded library)
It builds and runs in adb shell but I cannot capture frame and thus write to the image file. I checked the logcat output and it seems to load the libraries and opens the camera but then it gets stuck at "capture>>frame" step.
Any ideas?
Thanks
Zafer
I want to compile this program for Android and see it run on my phone:
#include "Hello World.h"
using namespace codewerks;
//=============================================
// Main Loop
//=============================================
int main(int argc, char* argv[])
{
Print(std::string("Hello World!"));
}
Where do I start? Can I compile this with GCC? The NDK seems focused on Java. Thank you.
This is now possible with the latest NDK. You will need an emulator or phone running Android 2.3 to try it, but the NativeActivity documentation has a complete example.
Unfortunately it is somewhat more complicated than a simple "hello world" example, and "main" is spelled "android_main". You still need to worry about your application life cycle as you do in Java, and the only real way to draw to the screen is to use OpenGL ES. It seems to be designed for writing games for Android.
Build as executable. (BUILD_EXECUTABLE)
Copy the executable to sdcard. (adb push)
Go to android shell. (adb shell)
Change the permission of the executable. (chmod 777)
Run the executable. (./out)
You will see the printed result on the console. (happy?)