No implementation found for native Stitch - android

I use opencv stitching in android project.
public class MainActivity extends Activity implements OnClickListener {
private String mWarpType;
private String mMatchConf;
private String mConfThresh;
private SharedPreferences mSettings;
public static final String SETTINGS = "Pano_Settings";
private final String SETTINGS_WARP_TYPE = "warp";
private final String SETTINGS_MATCH_CONF = "match_conf";
private final String SETTINGS_CONF_THRESH = "conf_thresh";
private String mDefaultWarpType = "spherical";
private String mDefaultMatchConf = "0.5";
private String mDefaultConfThresh = "0.8";
...
public native int Stitch(Object[] args);
public void onClick(View v) {
switch (v.getId()) {
case R.id.GoButton:
List<String> s = new ArrayList<String>();
s.add("Stitch");
s.add("/sdcard/tesseract/images1.jpeg");
s.add("/sdcard/tesseract/images2.jpeg");
s.add("--warp");
s.add(mWarpType);
s.add("--conf_thresh");
s.add(mConfThresh);
s.add("--match_conf");
s.add(mMatchConf);
s.add("--work_megapix");
s.add("0.2");
s.add("--seam_megapix");
s.add("0.2");
s.add("--expos_comp");
s.add("gain");
s.add("--output");
s.add("/sdcard/tesseract/");
Integer i = Stitch(s.toArray());
Log.d("1",i.toString());
break;
default:
break;
}
}
}
application is started but when Stitch(s.toArray()) is called I get the error:
W/dalvikvm(15392): No implementation found for native Lcom/prototype/MainActivity;.Stitch ([Ljava/lang/Object;)I
OpenCV successfully added in the workplace and my project -> Properties -> Android -> Library add -> OpenCV lib project
version OpenCV 2.4.2.
sample was taken from the project android-opencv-panorama.

You probably copied the native code "as is" from the sample, but your Java class has a different package and name. Look for the function named Java_<some more>_Stitch() in your cpp file, and rename it to become:
Java_com_prototype_MainActivity_Stitch()

Related

What are some examples of MediaController commands?

Checking out the MediaController documentation, I noticed that there is a function called sendCommand(...), which requires three parameters:
command: String;
args: Bundle;
cb: ResultReceiver.
But examples of how to use that method are nowhere to be found.
What are the available MediaController#sendCommand(...) default commands and acceptable argument keys and values types?
For example, checking PlaybackState documentation, we can find a constant called ACTION_PLAY_FROM_MEDIA_ID which description is as follows:
Indicates this session supports the play from media id command
This leads us to think that MediaController#sendCommand(...) is able to change a MediaSession's current media by sending it the media ID. How can we do it?
It's known that Google Play Music App's MediaController shares its Media Queue through MediaController#getQueue function.
You can find Commands constants in MediaControllerCompat.
They actually are:
public static final String COMMAND_GET_EXTRA_BINDER =
"android.support.v4.media.session.command.GET_EXTRA_BINDER";
public static final String COMMAND_ADD_QUEUE_ITEM =
"android.support.v4.media.session.command.ADD_QUEUE_ITEM";
public static final String COMMAND_ADD_QUEUE_ITEM_AT =
"android.support.v4.media.session.command.ADD_QUEUE_ITEM_AT";
public static final String COMMAND_REMOVE_QUEUE_ITEM =
"android.support.v4.media.session.command.REMOVE_QUEUE_ITEM";
public static final String COMMAND_REMOVE_QUEUE_ITEM_AT =
"android.support.v4.media.session.command.REMOVE_QUEUE_ITEM_AT";
public static final String COMMAND_ARGUMENT_MEDIA_DESCRIPTION =
"android.support.v4.media.session.command.ARGUMENT_MEDIA_DESCRIPTION";
public static final String COMMAND_ARGUMENT_INDEX =
"android.support.v4.media.session.command.ARGUMENT_INDEX";
For some basic usage samples u can check out its methods, like:
#Override
public void removeQueueItem(MediaDescriptionCompat description) {
long flags = getFlags();
if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
throw new UnsupportedOperationException(
"This session doesn't support queue management operations");
}
Bundle params = new Bundle();
params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
sendCommand(COMMAND_REMOVE_QUEUE_ITEM, params, null);
}

Config Transformations From Visual Studio (Xamarin)

I'm trying to implement a pre-build transformation to my Android.Manifest file within a Xamarin.Android project within Visual Studio - The purpose is simply to change the bundleID of my app depending on whether I build a debug or release version.
I've added a new .netFramework project to my solution, referenced Microsoft.Build and then added a new class named BuildTask and referenced the DLL in my Xamarin.Android project.
I then intend to add a UsingTask to my Xamarin.Android project's .csproj file at the very bottom, just above the closing tag - I presume this is correct.
Before I add the UsingTask I wanted to make sure the Xamarin.Android project builds, but unfortunately I'm getting errors about a missing reference in my Xamarin.Android project saying I'm missing a reference to System.Collections, but the error disappears the second I remove the reference to my new BuildTask.DLL
I've never done this before so I may be heading down the rabbit hole... If anyone's got any advise, it'd be greatly appreciated.
Here's my BuildTask class for reference:
using System;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System.Xml;
public class BuildTask : Task
{
private const string AndroidNamespace = "http://schemas.android.com/apk/res/android";
[Required]
public string PackageName { get; set; }
[Required]
public string ApplicationLabel { get; set; }
[Required]
public string ManifestFilename { get; set; }
public string Debuggable { get; set; }
public override bool Execute()
{
var xml = new XmlDocument();
xml.Load(ManifestFilename);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("android", AndroidNamespace);
if (xml.DocumentElement != null)
{
xml.DocumentElement.SetAttribute("package", PackageName);
var appNode = xml.DocumentElement.SelectSingleNode("/manifest/application", nsmgr);
if (appNode != null && appNode.Attributes != null)
{
var labelAttribute = appNode.Attributes["label", AndroidNamespace];
if (labelAttribute != null)
{
labelAttribute.Value = ApplicationLabel;
}
var debuggableAttribute = appNode.Attributes["debuggable", AndroidNamespace];
if (debuggableAttribute != null)
{
debuggableAttribute.Value = Debuggable;
}
xml.Save(ManifestFilename);
return true;
}
}
return false;
}
}
Thanks.
That because you are referencing full .NET Framework to Xamarin.Android project. This full .NET framework is incompatible with the Xamarin.Android. You should use one of the following:
Create an Android Library Project.
Create a Portable Class Library Project.
Create a Shared Project.

Get personal app code and display it

I am trying to get the app code and display it, for an example if button X starts a new activity then a textView displays the whole method
I reached only how can I display code in HTML format from this question
But is there is a way to get the code of my app out, I think that there are 2 ways
An Internal one by getting it by the app itself
An External one by reading the java file then filtering it and getting the text of the method
Is there are any ideas about that?
Thanks in advance
The above is not currently possible as mentioned by others is the comments. What i can suggest is shipping your application with the source code in the assets folder and using a helper function to extract a certain methods from the source at runtime (your second proposed approach). I have written example code but it is in pure java and needs to be ported to android (a few lines).
NB: You may need to reformat the code after extraction depending on your use case.
Hope it helps :)
The code for the helper method:
static String getTheCode(String classname ,String methodSignature ) throws FileNotFoundException {
//**********************A few lines of code below need changing when porting ***********//
// open file, your will be in the assets folder not in the home dir of user, don't forget the .java extension when porting
File file = new File(System.getProperty("user.home") +"/"+ classname +".java");
// get the source, you can use FileInputReader or some reader supported by android
Scanner scanner = new Scanner(file);
String source = "";
while(scanner.hasNext()) {
source += " "+ scanner.next();
}
//**********************The above code needs changing when porting **********//
// extract code using the method signature
methodSignature = methodSignature.trim();
source = source.trim();
//appending { to differentiate from argument as it can be matched also if in the same file
methodSignature = methodSignature+"{";
//making sure we find what we are looking for
methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "(");
methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")");
methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ",");
methodSignature = methodSignature.replaceAll("\\s+", " ");
source =source.replaceAll("\\s*[(]\\s*", "(");
source = source.replaceAll("\\s*[)]\\s*", ")");
source = source.replaceAll("\\s*[,]\\s*", ",");
source = source.replaceAll("\\s+", " ");
if(!source.contains(methodSignature)) return null;
// trimming all text b4 method signature
source = source.substring(source.indexOf(methodSignature));
//getting last index, a methods ends when there are matching pairs of these {}
int lastIndex = 0;
int rightBraceCount = 0;
int leftBraceCount = 0;
char [] remainingSource = source.toCharArray();
for (int i = 0; i < remainingSource.length ; i++
) {
if(remainingSource[i] == '}'){
rightBraceCount++;
if(rightBraceCount == leftBraceCount){
lastIndex = (i + 1);
break;
}
}else if(remainingSource[i] == '{'){
leftBraceCount++;
}
}
return source.substring(0 ,lastIndex);
}
Example usage (getTheCode methods is static and in a class called GetTheCode):
public static void main(String... s) throws FileNotFoundException {
System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut()"));
System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut(String word)"));
}
Output:
private static void shoutOut(){ // nothing to here }
private static void shoutOut(String word){ // nothing to here }
NB: When starting your new activity create a method eg
private void myStartActivty(){
Intent intent = new Intent(MyActivity.this, AnotherActivity.class);
startActivity(intent);
}
Then in your onClick:
#Override
public void onClick(View v) {
myStartActivity();
myTextView.setText(GetTheCode.getTheCode("MyActivity","private void myStartActivity()"));
}
Update: Ported the Code for android:
import android.content.Context;
import java.io.IOException;
import java.util.Scanner;
public class GetTheCode {
static String getTheCode(Context context, String classname , String methodSignature ) {
Scanner scanner = null;
String source = "";
try {
scanner = new Scanner(context.getAssets().open(classname+".java"));
while(scanner.hasNext()) {
source += " "+ scanner.next();
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
scanner.close();
// extract code using the method signature
methodSignature = methodSignature.trim();
source = source.trim();
//appending { to differentiate from argument as it can be matched also if in the same file
methodSignature = methodSignature+"{";
//making sure we find what we are looking for
methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "(");
methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")");
methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ",");
methodSignature = methodSignature.replaceAll("\\s+", " ");
source =source.replaceAll("\\s*[(]\\s*", "(");
source = source.replaceAll("\\s*[)]\\s*", ")");
source = source.replaceAll("\\s*[,]\\s*", ",");
source = source.replaceAll("\\s+", " ");
if(!source.contains(methodSignature)) return null;
// trimming all text b4 method signature
source = source.substring(source.indexOf(methodSignature));
//getting last index, a methods ends when there are matching pairs of these {}
int lastIndex = 0;
int rightBraceCount = 0;
int leftBraceCount = 0;
char [] remainingSource = source.toCharArray();
for (int i = 0; i < remainingSource.length ; i++
) {
if(remainingSource[i] == '}'){
rightBraceCount++;
if(rightBraceCount == leftBraceCount){
lastIndex = (i + 1);
break;
}
}else if(remainingSource[i] == '{'){
leftBraceCount++;
}
}
return source.substring(0,lastIndex);
}
}
Usage:
// the method now takes in context as the first parameter, the line below was in an Activity
Log.d("tag",GetTheCode.getTheCode(this,"MapsActivity","protected void onCreate(Bundle savedInstanceState)"));
Let's start with a broader overview of the problem:
Display App code
Press X button
Open new activity with a textview which displays the method
The goal is to do the following:
Viewing app method by extracting it and then building & running it.
There are some methods we can use to run Java/Android code dynamically. The way I would personally do it is DexClassLoader and with Reflection.
If you need more details, let me know. Here is what it'd do though:
View app method
Upon pressing X, launch intent with extra to new Activity
Parse and compile code dynamically and then run it with DexClassLoader and Reflection
Sources:
Sample file loading Java method from TerminalIDE Android App
Android Library I made for Auto-Updating Android Applications without needing the Play Store on non-root devices

How to use the Android light sensor in Unity

I want to use the light sensor on Android with Unity. Unity can't do this and there is no asset/plugin on the store who could do that. And google isn't so frendly with this question...
Simple version
This part explain how to use my code.
Put the .jar file into Assets/Plugins/Android folder
Then simply add the script LightSensorPluginScript.cs on the GameObject you wanted.
Then if you want to get the sensor value:
TextMesh tm;
LightSensorPluginScript test;
void Start() {
tm = transform.GetComponent<TextMesh>();
test = GetComponent<LightSensorPluginScript> ();
}
void Update() {
tm.text = test.getLux().ToString();
}
All the files can be found in this zip archive
Detailed version
This part explain how to create the plugin.
First of all you have to create an Android library. If you are using Android Studio, they are converted into .aar files. Extract them like a zip file and you will find a classes.jar file which is the correct .jar you want. You can rename it as you want, Unity didn't care.
Android Java code
public class LightSensorLib{
private SensorManager mSensorManager;
private Sensor mSensorRot;
private float lux = -1000;
public void init(Context context) {
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mSensorRot = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
SensorEventListener mySensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
float sensorData[];
if(event.sensor.getType()== Sensor.TYPE_LIGHT) {
sensorData = event.values.clone();
lux = sensorData[0];
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
};
mSensorManager.registerListener(mySensorEventListener, mSensorRot, 500);
}
public float getLux () {
return lux;
}
}
Then I have a C# script who does the bridge between Android Java and Unity
C# Bridge code
public class LightSensorPluginScript : MonoBehaviour {
private AndroidJavaObject activityContext = null;
private AndroidJavaObject jo = null;
AndroidJavaClass activityClass = null;
void Start () {
#if UNITY_ANDROID
activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
jo = new AndroidJavaObject("com.etiennefrank.lightsensorlib.LightSensorLib");
jo.Call("init", activityContext);
#endif
}
public float getLux() {
#if UNITY_ANDROID
return jo.Call<float>("getLux");
#endif
}
}
Now you can do what is explained in the Simple version part of this post to use the sensor.
If you want any precision I would be glad to answer and update the post.
For the IOs version I'm sorry but I have no mac to develop this... So if you want to lend me one I would be glad to do it.
I could add it as a plugin on the asset store but it feels a bit cumbersome. So I prefer to post it on StackOverflow where the post editor is really neat.
At last I hope it helps some developers.
using UnityEngine;
using System;
using System.Collections;
public class LightSensorPluginScript : MonoBehaviour {
private AndroidJavaObject activityContext = null;
private AndroidJavaObject jo = null;
AndroidJavaClass activityClass = null;
public TextMesh tm;
LightSensorPluginScript test;
void Start () {
#if UNITY_ANDROID
activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
tm = transform.GetComponent<TextMesh>();
test = GetComponent<LightSensorPluginScript>();
jo = new AndroidJavaObject("com.etiennefrank.lightsensorlib.LightSensorLib");
jo.Call("init", activityContext);
#endif
}
public float getLux() {
#if UNITY_ANDROID
return jo.Call<float>("getLux");
#endif
}
void Update()
{
tm.text = test.getLux().ToString();
}
}

Calling a Unity C# method that returns a value from Android/Java

I am developing an Android plugin for Unity and I am wondering if there is a way in the Android code to call a Unity C# method that returns a value and get this value.
Of course this will NOT work but is there a way, tips, tricks to achieve something like this:
String myReturnedString = UnityPlayer.UnitySendMessage("MyGameObject",
"ReturnThisString","hello");
Many thanks for your help.
In Android:
int Times_Called;
public int Get_Times_Called()
{
Times_Called += 1;
return Times_Called;
}
In Unity
AndroidJavaClass Java = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject AndroidActivity = Java.GetStatic<AndroidJavaObject>("currentActivity");
int Times_Called = AndroidActivity.Call<int>("Get_Times_Called");
Debug.Log("Get_Times_Called: " + Times_Called);
One way is to have a method in your Unity program that communicates with your Android application through a method in your Android app, by using AndroidJavaObject.Call in your Unity class.
e.g.
You have this method in your Android application.
AndroidActivity.java
String stringFromUnity = "";
public void setStringFromUnity(String input){
stringFromUnity = input;
}
Then in your Unity script (I am using C#).
UnityScript.cs
// Get the UnityPlayer class
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
// Get the current activity
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
// Call the setStringFromUnity method from Android Activity
activity.Call("setStringFromUnity", "Here is a string for you, Android");
OR we can set the String directly using the AndroidJavaObject.Set method.
// Set the String directly provided the String is public
activity.Set<string>("stringFromUnity", "I set your String directly, hah!");
Hope this helps.
For reference, you can search for "Unity Plugins for Android" or take a look at Unity documentation at this link.
First, we create a method 'reverse' in UnityPlayerActivity
UnityPlayerActivity.java:
public class UnityPlayerActivity extends Activity {
...
public String reverse(String str) {
return new StringBuilder(str).reverse().toString();
}
...
}
Then we call next block somewhere in Unity (e.g. in Monobehaviour):
private static void CallAndroidMethod()
{
var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
var args = new object[1];
args[0] = "Hello World!";
var reversed = currentActivity.Call<string>("reverse", args);
Debug.Log($"Reversed: {reversed}");
}
Finally, checking the Log (e.g. in AndroidStudio):
I/Unity: Reversed: !dlroW olleH

Categories

Resources