Rottjung Rottjung - 3 months ago 38
Android Question

Android studio project to Unity 5

I made a notification service project in android studio which runs perfect on lollipop.
now I'm trying to make it into a plugin for Unity 5. but once build it keeps crashing on start up...

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.techlab.samanthaplugin" >

<application
android:allowBackup="true"
android:label="SamanthaPlugin">
<activity
android:name="com.techlab.samanthaplugin.MainActivity"
android:label="SamanthaPlugin" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.techlab.samanthaplugin.NotificationService"
android:label="SamanthaPlugin"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">

<intent-filter>

<action android:name="android.service.notification.NotificationListenerService" />

</intent-filter>

</service>

</application>




NotificationService class:

package com.techlab.samanthaplugin;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;


public class NotificationService extends NotificationListenerService {

Context context;

@Override

public void onCreate() {

super.onCreate();
context = getApplicationContext();

}
@Override

public void onNotificationPosted(StatusBarNotification sbn) {


String pack = sbn.getPackageName();
String ticker = sbn.getNotification().tickerText.toString();
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();

Log.i("Package",pack);
Log.i("Ticker",ticker);
Log.i("Title",title);
Log.i("Text",text);

Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("package", pack);
msgrcv.putExtra("ticker", ticker);
msgrcv.putExtra("title", title);
msgrcv.putExtra("text", text);

LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);


}

@Override

public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i("Msg","Notification Removed");

}
}


MainActivity:

package com.techlab.samanthaplugin;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;


public class MainActivity extends Activity {

//TableLayout tab;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
//tab = (TableLayout)findViewById(R.id.tab);
LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, new IntentFilter("Msg"));

}


private BroadcastReceiver onNotice= new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String pack = intent.getStringExtra("package");
String title = intent.getStringExtra("title");
String text = intent.getStringExtra("text");



//TableRow tr = new TableRow(getApplicationContext());
//tr.setLayoutParams(new TableRow.LayoutParams( TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
//TextView textview = new TextView(getApplicationContext());
//textview.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT,1.0f));
//textview.setTextSize(20);
//textview.setTextColor(Color.parseColor("#0B0719"));
//textview.setText(Html.fromHtml(pack +"<br><b>" + title + " : </b>" + text));
//tr.addView(textview);
//tab.addView(tr);
}
};
}


build.gradle:

apply plugin: 'com.android.library'

android {
compileSdkVersion 21
buildToolsVersion "21.0.2"

defaultConfig {
//applicationId "techlab.samanthaplugin"
minSdkVersion 19
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.android.gms:play-services:6.1.71'
compile files('libs/classes.jar')
}
//task to delete the old jar
task deleteOldJar(type: Delete) {
delete 'release/AndroidPlugin.jar'
}

//task to export contents as jar
task exportJar(type: Copy) {
from('build/intermediates/bundles/release/')
into('release/')
include('classes.jar')
///Rename the jar
rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteOldJar, build)


I can't seem to find which one of these is responsible for the crash. :-(

Answer

found out what's wrong, so i'll post it as answer. making an Android Studio application into a Unity 5 plugin:

so first of all you need to turn the project into a library. you can do this by copying the Unity classes.jar into the app/libs folder. you can find the classes.jar on pc in

C:\Program Files (x86)\Unity\Editor\Data\PlaybackEngines\androidplayer\release\bin

and on Mac

Applications\Unity(rightclick Show Package Content)PlaybackEngines\AndroidPlayer\Variations\Release\Classes

rightclick on the classes.jar in your Android Studio app and select Add as Library. Add it to your app.

open the build.gradle from your app folder and paste this add the bottom of it.

//task to delete the old jar
task deleteOldJar(type: Delete) {
    delete 'release/AndroidPlugin.jar'
}

//task to export contents as jar
task exportJar(type: Copy) {
    from('build/intermediates/bundles/release/')
    into('release/')
    include('classes.jar')
    ///Rename the jar
    rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteOldJar, build)

then sync it. now if you open the gradle tab on the right and navigate the "other" task folder to find the exportJar task. double clicking it will build you a AndroidPlugin.jar in app/release this together with your Manifest.xml should go into unity, in Assets/Plugins/Android (you create the folders you need)

for a recap i got it from this

now for the part that confused me in converting the project. you always need a class in your Android Studio project that extends UnityPlayerActivity. This is the bridge between your unity project and your android studio project.

so that you can compare the changes with the above code, i'll repost the code that worked (the manifest and the gradle almost stayed the same the big change was in the MainActivity.java:

so MainActivity class:

package com.techlab.pluginsamantha;

import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {

    public String GetSenderName()
    {
        String senderName = NotificationService.sender;
        return senderName;
    }
    public String GetAppName()
    {
        String appName = NotificationService.appName;
        return appName;
    }
    public String GetTitle()
    {
        String textTitle = NotificationService.titleText;
        return textTitle;
    }
    public String GetBody()
    {
        String textBody = NotificationService.bodyText;
        return textBody;
    }
    public boolean GetNewNotification()
    {
        return NotificationService.newNotification;
    }
}

the NotificationService class:

package com.techlab.pluginsamantha;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;


public class NotificationService extends NotificationListenerService {

    Context context;
    public static String appName;
    public static String sender;
    public static String titleText;
    public static String bodyText;
    public static boolean newNotification;

    @Override

    public void onCreate() {

        super.onCreate();
        context = getApplicationContext();

    }
    @Override

    public void onNotificationPosted(StatusBarNotification sbn) {

        newNotification = true;
        String pack = sbn.getPackageName();
        appName = pack;
        String ticker = sbn.getNotification().tickerText.toString();
        sender = ticker;
        Bundle extras = sbn.getNotification().extras;
        String title = extras.getString("android.title");
        titleText = title;
        String text = extras.getCharSequence("android.text").toString();
        bodyText = text;

        newNotification = false;

    }

    @Override

    public void onNotificationRemoved(StatusBarNotification sbn) {
        Log.i("Msg","Notification Removed");

    }
}

this is my PluginController script in unity:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Runtime.InteropServices;

public class PluginController : MonoBehaviour {

    public GUISkin skin;
    public List<Notification> notifications = new List<Notification>();
    string bodyText = "";

    public string GetSenderName()
    {
        AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        return currentActivity.Call<string>("GetSenderName");
    }
    public string GetAppName()
    {
        AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        return currentActivity.Call<string>("GetAppName");
    }

    public string GetTitleText()
    {
        AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        return currentActivity.Call<string>("GetTitle");
    }
    public string GetBodyText()
    {
        AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        return currentActivity.Call<string>("GetBody");
    }
    public bool GetNewNotification()
    {
        AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        return currentActivity.Call<bool>("GetNewNotification");
    }
    void Update()
    {
        if(GetNewNotification())
            CopyNotification();
    }
    public void CopyNotification()
    {
        if(bodyText != GetBodyText())
        {
            Notification note = new Notification();
            note.SenderName = GetSenderName();
            note.AppName = GetAppName();
            note.TitleText = GetTitleText();
            note.TitleLength = note.TitleText.Length;
            note.BodyText = GetBodyText();
            note.BodyLength = note.BodyText.Length;
            notifications.Add(note);
            bodyText = GetBodyText();
        }
    }
    void OnGUI()
    {
        GUI.skin = skin;
        foreach(Notification n in notifications)
        {
            GUILayout.Label("SenderName: "+n.SenderName);
            GUILayout.Label("AppName: "+n.AppName);
            GUILayout.Label("TitleText: "+n.TitleText+" :length: "+n.TitleLength.ToString());
            GUILayout.Label("BodyText: "+n.BodyText+" :length: "+n.BodyLength.ToString());
        }
    }
}