-
Notifications
You must be signed in to change notification settings - Fork 1.9k
SL4A integration: SL4A's extensive API can be used before a total pyjnius port #191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
34046cf
00a46f8
852b5f7
5f0dc28
4ce361c
c4e48c6
2c197c3
38dd4f2
18c6e73
88a692d
1770e08
6bba820
be5c49b
db9f92c
47a9d9a
4c77510
eca29e4
1585b27
520c7ed
e6c0746
199f60d
34ef838
5a6fa9e
7fd415c
3301ec5
850ce97
ac7a60d
ad030b2
799ad19
4d2559c
0897e83
a74e7b7
4801ad1
d33c6e8
653d2c6
54c25b6
9e80fab
6fab3e3
3e11f25
54b2479
6d9629c
7eba72d
7ac9f72
628fdcc
e6bd081
41a3301
c6b3ba7
28572df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/bin/bash | ||
|
||
URL_sl4acompat=https://github.com/damonkohler/sl4a/raw/dcfa832f80/android/script_for_android_template.zip | ||
DEPS_sl4acompat=() | ||
MD5_sl4acompat=eed6a34bdf63e57a94b3c61528b6a577 | ||
BUILD_sl4acompat=$BUILD_PATH/sl4acompat/ | ||
RECIPE_sl4acompat=$RECIPES_PATH/sl4acompat | ||
|
||
function prebuild_sl4acompat() { | ||
true | ||
} | ||
|
||
function shouldbuild_sl4acompat() { | ||
true | ||
} | ||
|
||
function build_sl4acompat() { | ||
true | ||
} | ||
|
||
function postbuild_sl4acompat() { | ||
cd $BUILD_sl4acompat | ||
mkdir "$DIST_PATH"/libs | ||
cp -a libs/* "$DIST_PATH"/libs/ | ||
cd - | ||
true | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -383,6 +383,8 @@ def make_package(args): | |
ap.add_argument('--add-jar', dest='add_jar', action='append', help='Add a Java .jar to the libs, so you can access its classes with pyjnius. You can specify this argument more than once to include multiple jars') | ||
ap.add_argument('--meta-data', dest='meta_data', action='append', | ||
help='Custom key=value to add in application metadata') | ||
ap.add_argument('--sl4acompat', dest='sl4acompat', action='store_true', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the recipe was included in the distribution, i guess the build.py should not expose this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hum... I see your point, but I really dont understand what you mean with "the token that jinja should add by default, and then a recipe can add its own token during the distribution part". If this could be made, is very nice as the recipes can "push" their own needs to the AndroidManifes.xml in the future, like BT permissions for some PyBluez recipe... Anyway, I am willing to accept your suggestion, as soon as I can understand how to do this. |
||
help='Provide this argument to include SL4A jars and RPC service into the app.') | ||
|
||
args = ap.parse_args() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
* Copyright (C) 2010 Google Inc. | ||
* Copyright (C) 2014 Alan Justino | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
|
||
package org.alanjds.sl4acompat; | ||
|
||
import android.app.Notification; | ||
import android.app.PendingIntent; | ||
import android.content.Intent; | ||
import android.os.Binder; | ||
import android.os.IBinder; | ||
import android.os.AsyncTask; | ||
|
||
import com.googlecode.android_scripting.AndroidProxy; | ||
import com.googlecode.android_scripting.ForegroundService; | ||
import com.googlecode.android_scripting.Log; | ||
import com.googlecode.android_scripting.NotificationIdFactory; | ||
import com.googlecode.android_scripting.jsonrpc.RpcReceiverManager; | ||
|
||
import java.net.InetSocketAddress; | ||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
/** | ||
* A service that allows scripts and the RPC server to run in the background. | ||
* | ||
* @author Alexey Reznichenko (alexey.reznichenko@gmail.com) | ||
* @author Manuel Naranjo (manuel@aircable.net) | ||
* @author Alan Justino (alan.justino@yahoo.com.br) | ||
*/ | ||
public class MinimalService extends ForegroundService { | ||
private final static int NOTIFICATION_ID = NotificationIdFactory.create(); | ||
private final CountDownLatch mLatch = new CountDownLatch(1); | ||
private final IBinder mBinder; | ||
|
||
//private InterpreterConfiguration mInterpreterConfiguration; | ||
private RpcReceiverManager mFacadeManager; | ||
private AndroidProxy mProxy; | ||
private InetSocketAddress mAddressWithPort; | ||
private String mProxyAddress; | ||
|
||
public class LocalBinder extends Binder { | ||
public MinimalService getService() { | ||
return MinimalService.this; | ||
} | ||
} | ||
|
||
public MinimalService() { | ||
super(NOTIFICATION_ID); | ||
mBinder = new LocalBinder(); | ||
} | ||
|
||
@Override | ||
public IBinder onBind(Intent intent) { | ||
return mBinder; | ||
} | ||
|
||
@Override | ||
public void onCreate() { | ||
super.onCreate(); | ||
} | ||
|
||
@Override | ||
public void onStart(Intent intent, final int startId) { | ||
Log.v("Starting MinimalService"); | ||
super.onStart(intent, startId); | ||
|
||
mProxy = new AndroidProxy(this, null, true); | ||
mProxyAddress = startProxy(); | ||
mLatch.countDown(); | ||
} | ||
|
||
private String startProxy() { | ||
Log.v("Starting AndroidProxy"); | ||
mAddressWithPort = mProxy.startLocal(); | ||
Log.v("Started AndroidProxy"); | ||
|
||
if (mAddressWithPort == null) { Log.w("Oops: mAddressWithPort == null"); } | ||
Log.v(String.format("Started at %s", mAddressWithPort.toString())); | ||
|
||
String host = mAddressWithPort.getHostName(); | ||
Integer iPort = mAddressWithPort.getPort(); | ||
String port = iPort.toString(); | ||
String handshake = mProxy.getSecret(); | ||
String proxyAddress = String.format("%s@%s:%s", handshake, host, port); | ||
Log.d(String.format("AndroidProxy at: %s@%s:%s", handshake, host, port)); | ||
|
||
Intent netaddress = new Intent("org.alanjds.sl4acompat.STORE_RPC_NETADDRESS"); | ||
netaddress.putExtra("host", host); | ||
netaddress.putExtra("port", port); | ||
netaddress.putExtra("handshake", handshake); | ||
sendBroadcast(netaddress); | ||
Log.v("Sent 'org.alanjds.sl4acompat.STORE_RPC_NETADDRESS'"); | ||
|
||
return proxyAddress; | ||
} | ||
|
||
RpcReceiverManager getRpcReceiverManager() throws InterruptedException { | ||
mLatch.await(); | ||
if (mFacadeManager==null) { // Facade manage may not be available on startup. | ||
mFacadeManager = mProxy.getRpcReceiverManagerFactory() | ||
.getRpcReceiverManagers().get(0); | ||
} | ||
return mFacadeManager; | ||
} | ||
|
||
@Override | ||
protected Notification createNotification() { | ||
PendingIntent contentIntent = PendingIntent.getService(this, 0, new Intent(), 0); | ||
// This contentIntent is a noop. | ||
|
||
Notification notification = new Notification(); | ||
//.setContentTitle("SL4A Facade") | ||
//.setContentText("minimal SL4A facade running") | ||
//.setContentIntent(contentIntent) | ||
//.build(); | ||
|
||
//NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); | ||
notification.flags |= Notification.FLAG_AUTO_CANCEL; // hide the notification after its selected | ||
|
||
//notificationManager.notify(0, notification); | ||
return notification; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package org.alanjds.sl4acompat; | ||
|
||
import com.googlecode.android_scripting.Log; | ||
|
||
import android.content.BroadcastReceiver; | ||
import android.content.Context; | ||
import android.content.Intent; | ||
|
||
|
||
// Usage: ./adb shell am broadcast -a org.alanjds.sl4acompat.START_MINIMAL_SERVICE | ||
|
||
public class MinimalServiceStarter extends BroadcastReceiver { | ||
|
||
@Override | ||
public void onReceive(Context context, Intent intent) { | ||
Log.v("Received intent!"); | ||
Intent serviceIntent = new Intent(context, MinimalService.class); | ||
context.startService(serviceIntent); | ||
Log.v("Service started?"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright (C) 2010 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
|
||
package org.alanjds.sl4acompat; | ||
|
||
import android.app.Activity; | ||
import android.content.ComponentName; | ||
import android.content.Context; | ||
import android.content.Intent; | ||
import android.content.ServiceConnection; | ||
import android.os.Bundle; | ||
import android.os.IBinder; | ||
|
||
import com.googlecode.android_scripting.Constants; | ||
import com.googlecode.android_scripting.facade.ActivityResultFacade; | ||
import com.googlecode.android_scripting.jsonrpc.RpcReceiverManager; | ||
|
||
/** | ||
* @author Alexey Reznichenko (alexey.reznichenko@gmail.com) | ||
*/ | ||
public class ScriptActivity extends Activity { | ||
|
||
@Override | ||
protected void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
if (Constants.ACTION_LAUNCH_SCRIPT_FOR_RESULT.equals(getIntent().getAction())) { | ||
setTheme(android.R.style.Theme_Dialog); | ||
//setContentView(R.layout.dialog); | ||
ServiceConnection connection = new ServiceConnection() { | ||
@Override | ||
public void onServiceConnected(ComponentName name, IBinder service) { | ||
MinimalService scriptService = ((MinimalService.LocalBinder) service).getService(); | ||
try { | ||
RpcReceiverManager manager = scriptService.getRpcReceiverManager(); | ||
ActivityResultFacade resultFacade = manager.getReceiver(ActivityResultFacade.class); | ||
resultFacade.setActivity(ScriptActivity.this); | ||
} catch (InterruptedException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void onServiceDisconnected(ComponentName name) { | ||
// Ignore. | ||
} | ||
}; | ||
bindService(new Intent(this, MinimalService.class), connection, Context.BIND_AUTO_CREATE); | ||
startService(new Intent(this, MinimalService.class)); | ||
} else { | ||
//ScriptApplication application = (ScriptApplication) getApplication(); | ||
//if (application.readyToStart()) { | ||
startService(new Intent(this, MinimalService.class)); | ||
//} | ||
finish(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package org.alanjds.sl4acompat; | ||
|
||
import com.googlecode.android_scripting.BaseApplication; | ||
import com.googlecode.android_scripting.Log; | ||
import com.googlecode.android_scripting.interpreter.InterpreterConfiguration; | ||
import com.googlecode.android_scripting.interpreter.InterpreterConstants; | ||
import com.googlecode.android_scripting.interpreter.InterpreterConfiguration.ConfigurationObserver; | ||
|
||
import java.util.concurrent.CountDownLatch; | ||
|
||
public class Sl4aCompatibleApplication extends BaseApplication implements ConfigurationObserver { | ||
|
||
private volatile boolean receivedConfigUpdate = true; | ||
private final CountDownLatch mLatch = new CountDownLatch(1); | ||
|
||
@Override | ||
public void onCreate() { | ||
mLatch.countDown(); | ||
} | ||
|
||
@Override | ||
public void onConfigurationChanged() { } | ||
|
||
public boolean readyToStart() { | ||
try { | ||
mLatch.await(); | ||
} catch (InterruptedException e) { | ||
Log.e(e); | ||
} | ||
return receivedConfigUpdate; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, use the same construction as we do in kivy/others libs, ie, extract the version in a variable, then we can use
sl4acompat==<version>
.Example in Kivy:
VERSION_kivy=${VERSION_kivy:-stable}
:stable
is the default version.