I have been developing a number of Android activities in a project in Eclipse.
I am now following a tutorial to achieve push notifications and I need to create a new Android Application (extends Application in the code).
However, when trying to create this application it does not run properly. Does the class name need to be the same as the project title?
When trying to run this on my phone it crashes.
My code is below: (ApplicationLoader is not the name of the App/Project)
public class ApplicationLoader extends Application {
#Override
public void onCreate() {
super.onCreate();
//Configure your application
//
// This can be done in code as illustrated here,
// or you can add these settings to a properties file
// called airshipconfig.properties
// and place it in your "assets" folder
AirshipConfigOptions options = AirshipConfigOptions.loadDefaultOptions(this);
options.developmentAppKey = --my development app key
options.productionAppKey = --my production app key
options.inProduction = false; //determines which app key to use
Logger.logLevel = Log.VERBOSE;
// Take off initializes the services
UAirship.takeOff(this, options);
PushManager.enablePush();
PushPreferences prefs = PushManager.shared().getPreferences();
Logger.info("My Application onCreate - App APID: " + prefs.getPushId());
}
}
If your application name is ApplicationLoader (defined under application tag in your AndroidManifest) then Application Class name should also be ApplicationLoader
<application android:name="ApplicationLoader ">
public class ApplicationLoader extends Application
Related
This is pretty basic, but I'm not getting success on implementing it from the official Unity docs and YouTube video tutorials, so I asked.
I want to access methods from already made aar plug-in. Its checked as android plug-in by default. The plug-in has following code:
package alarm.company.com.unity;
public class myPlugin {
public String myTest(int i){
return "Hello your string number is: "+i;
}
}
the compiled aar plug-in is copied into the Unity folder.
Here's the c# code to access that method:
const string PluginName = "alarm.company.com.unity.myPlugin";
static AndroidJavaClass _pluginClass;
static AndroidJavaClass _pluginInstance;
public Text text;
// Start is called before the first frame update
void Start()
{
AndroidJavaClass plugin = new AndroidJavaClass(PluginName);
string s = plugin.CallStatic<string>("myTest", 9);
print(s);
text.text = s;
}
text is assigned and this script is put on the main camera. But I'm not getting any text back or the text object is not changed, while running in emulator. How can this be solved?
Unity Plugin development is a bit tricky to get setup at first but once you are able to it is pretty powerful.
Couple things.
1) You are using an AndroidJavaClass and trying to call a non static method in java. Your method in your plugin should be static if you are wanting to use that class.
2) Otherwise you will need to use an AndroidJavaObject to construct your class and then you should be able to call your function.
Hope this helps!
Example Using non Static Code:
Unity Code
using (AndroidJavaObject leetPlugin = new AndroidJavaObject("alarm.company.com.unity.myPlugin")){
string s = leetPlugin.Call("myTest", 9);
print(s);
text.text = s;
}
Android Code
public void myTest(int value) {
return "Your value is " + value;
}
Some advises when you work with plugins for unity:
Use gradle build system. It generates mainTemplate file in Plugins/Android. You can edit this file and set source java code to your java classes so you don't need to generate aar every time you want to build:
sourceSets
{
main
{
java
{
srcDirs = ['src']
srcDirs += ['E:/AndroidStudioProjects/PathToJavaClasses']
}
}
}
If you want to send something from java code to unity you should extend your activity from unity and call method UnitySendMessage
public class MyUnityPlayerActivity extends UnityPlayerActivity{
public void SendUnityMessage()
{
UnityPlayer.UnitySendMessage(UnityGameObjectName, UNITY_FUNCTION_NAME,
params);
}
}
I have a non visual class that need to read some files from the assets folder.
Is totally out-of-band so don't have a activity. How I can refer to it without pass down the activity?
Also I can accept a alternative to the assets way to put files (like .sql) to be read later on the android devices.
P.D:
This is a sample of the code where is called:
//Load asset not belong to anyone. Is that radical
let loadAsset(path:string) =
#if __ANDROID__
let sr = new StreamReader(?????.Assets.Open(path.Substring(1)))
seq {
while not sr.EndOfStream do
yield sr.ReadLine ()
}
#else
File.ReadLines(path)
#endif
What you really need is a Context. If you application has an Application class, you can use its Context to retrieve asset resources.
It should look something like this:
public class App extends Application {
public static Context context;
#Override public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
}
You can then used App.context to get resources/assets.
How to get an android asset without an Activity
Try using the following code:
let sr = new StreamReader(Android.App.Application.Context.Assets.Open(path.Substring(1)))
I am creating an ANE for Urban Airship, a service for sending push notifications (among other things). So far the integration has worked great but only when the app is open. When the app is exited, receiving a new push notification results in the app crashing with:
11-29 01:19:32.448 22340-22340/air.com.example.app E/Urban Airship Autopilot: Unable to takeOff automatically
11-29 01:19:32.496 22340-22440/air.com.example.app E/AndroidRuntime: FATAL EXCEPTION: IntentService[PushService]
Process: air.com.example.app, PID: 22340
java.lang.IllegalStateException: Take off must be called before shared()
at com.urbanairship.UAirship.shared(UAirship.java:147)
at com.urbanairship.BaseIntentService.onHandleIntent(BaseIntentService.java:94)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.os.HandlerThread.run(HandlerThread.java)
Through a lot of digging I believe the issue to be that I am calling UAirship.takeOff() from within TakeoffFunction (an FREFunction within my ANE) instead of calling it from the Application's main onCreate method (as is the issue seen in: UrbanAirship NPE)
Here is my TakeoffFunction:
public class TakeoffFunction implements FREFunction
{
#Override
public FREObject call(FREContext context, FREObject[] freObjects)
{
Log.d("TakeoffFunction", "Attempting Urban Airship TAKEOFF");
Application app = context.getActivity().getApplication();
Log.d("TakeoffFunction", "app found: " + app);
AirshipConfigOptions options = new AirshipConfigOptions();
options.developmentAppKey = "xxx";
options.developmentAppSecret = "xxx";
options.inProduction = false;
options.gcmSender = "000";
Log.d("TakeoffFunction", "Prepare to Launch...");
UAirship.takeOff(app, options, new UAirship.OnReadyCallback()
{
#Override
public void onAirshipReady(UAirship uAirship)
{
Log.d("TakeoffFunction", "Urban Airship is ready after takeoff");
uAirship.getPushManager().setUserNotificationsEnabled(true);
Log.d("TakeoffFunction", "User notifications have been enabled");
}
});
return null;
}
}
Thus, it would seem I need to somehow call UAirship.takeOff() from the main application's onCreate method. However, this is proving to be a challenge as I know that for Adobe AIR, there is an AppEntry class which functions as the main Application class, but this class is, as far as I know, barred from modification for developers. I found this tutorial: http://blogs.adobe.com/digitalmedia/2011/05/extending-air-for-android/ from back in 2011 before native extensions were officially supported. In there I see that they're able to override and extend the onCreate() method, but I don't know how I would go about doing the same thing with this native extension.
I would like to know if it is possible to extend the AppEntry's onCreate method or point AIR to a different AppEntry class altogether, overwriting the original.
Its common to see libs wanting to have the app initialize its module in the application's onCreate as its called before all services, receivers, or activities are created. Basically the only real entry point for all apps.
For frameworks like Adobe where its hard to call takeoff in the applicaiton file, we have added another way of calling takeoff using Autopilot.
Example:
public class AirAutopilot extends Autopilot {
#Override
public AirshipConfigOptions createAirshipConfigOptions(Context context) {
AirshipConfigOptions options = new AirshipConfigOptions();
options.developmentAppKey = "xxx";
options.developmentAppSecret = "xxx";
options.inProduction = false;
options.gcmSender = "000";
return options;
}
#Override
public void onAirshipReady(UAirship airship) {
Log.d("TakeoffFunction", "Urban Airship is ready after takeoff");
airship.getPushManager().setUserNotificationsEnabled(true);
Log.d("TakeoffFunction", "User notifications have been enabled");
}
}
Then add the autopilot class to the manifest in the application block (not sure about the Adobe Air way of doing this):
<meta-data android:name="com.urbanairship.autopilot" android:value="com.example.AirAutopilot" />
Then in your plugin, make sure a call to autopilot is made before accessing the UAirship instance:
Autopilot.automaticTakeOff(context.getActivity().getApplication());
Would it be a good idea to register GCM in an Application class like so:
public class MyApplication extends Application {
private GCMRegistrationUtil mGCMRegistrationUtil = GCMRegistrationUtil.getInstance(this);
#Override
public void onCreate() {
String registrationId = mGCMRegistrationUtil.registerDevice();
Log.d(TAG, "Device Registered Properly: " + registrationId);
}
It's working fine - I just am wondering if this could create any issues since it's inside an application class. I implemented it this was so it always checks to see if an id is stored in SharedPreferences immediately upon application startup, and if not go ahead and register.
By issues I am guessing maybe Performance issues?? Any potential for that?
Using NuGet I added Unity to my Xamarin.Forms Application.
In my App class constructor I want to newup a UnityContainer instance.
using Xamarin.Forms;
public class App : Application
{
public App ()
{
unityContainer = new UnityContainer();
// The root page of your application
this.MainPage = new NavigationPage(new HomePage());
}
private static IUnityContainer unityContainer;
}
Unfortunately a System.Reflection.TargetInvocationException. Is thrown on the line unityContainer = new UnityContainer(); as I start to run my app in the android emulator.
What could be the reason to this?