使用 pyjnius 在 python 中创建 Android Activity Context

GoB*_*g06 5 python java android kivy pyjnius

我正在使用以下代码将 Braintrees 嵌入式 UI 付款方式导入我的 python kivy 应用程序。

from jnius import autoclass
from jnius import cast
from android import activity

Intent = autoclass('android.content.Intent')
PythonActivity = autoclass('org.renpy.android.PythonActivity')

DropInRequest = autoclass('com.braintreepayments.api.dropin.DropInRequest')

#Global instance
instance = None
REQUEST = 1
RESULT_OK = 1

def onBraintreeSubmit(token):
    global instance

    def on_activity_result(request, response, data):
        global instance
        if request == REQUEST:
            print response
            if response == RESULT_OK:
                result = instance.getParcelableExtra(instance.EXTRA_DROP_IN_RESULT)
                nonce = result.getPaymentMethodNonce()
                print nonce
                return nonce

    activity.bind(on_activity_result=on_activity_result)
    instance = DropInRequest()
    instance.clientToken(token)
    intent = instance.getIntent(activity.this)
    PythonActivity.mActivity.startActivityForResult(intent,REQUEST)
Run Code Online (Sandbox Code Playgroud)

哪个试图模仿这个 Java 代码

DropInRequest dropInRequest = new DropInRequest()
    .clientToken(mClientToken);
startActivityForResult(dropInRequest.getIntent(context), DROP_IN_REQUEST);

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == DROP_IN_REQUEST) {
        if (resultCode == Activity.RESULT_OK) {
            DropInResult result = data.getParcelableExtra(DropInResult.EXTRA_DROP_IN_RESULT);
            String paymentMethodNonce = result.getPaymentMethodNonce().getNonce();
            // send paymentMethodNonce to your server
        } else if (resultCode == Activity.RESULT_CANCELED) {
            // canceled
        } else {
            // an error occurred, checked the returned exception
            Exception exception = (Exception) data.getSerializableExtra(DropInActivity.EXTRA_ERROR);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我需要将 Context 发送到 DropInRequest 类的 getIntent 函数,但我不知道如何使用 python-for-andriod 和 pyjnius 创建 Activity Context。下面是 getIntent 的 Java 方法。

public Intent getIntent(Context context) {
    return new Intent(context, DropInActivity.class)
            .putExtra(EXTRA_CHECKOUT_REQUEST, this);
}
Run Code Online (Sandbox Code Playgroud)

我想我需要将此包含在我的清单中,并使用 com.braintreepayments.api.BraintreeBrowserSwitchActivity 作为我的活动,但我不确定如何从中获取上下文。

<activity android:name="com.braintreepayments.api.BraintreeBrowserSwitchActivity"
    android:launchMode="singleTask">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="${applicationId}.braintree" />
    </intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)

我认为应该将这个类称为 BrowserSwitchActivity ,我需要从 BrowserSwitchActivity 获取上下文

package com.braintreepayments.api;

import com.braintreepayments.browserswitch.BrowserSwitchActivity;

/**
 * Helper Activity that captures the response when browser switch completes.
 */
public class BraintreeBrowserSwitchActivity extends BrowserSwitchActivity {
}
Run Code Online (Sandbox Code Playgroud)

最终将类扩展到活动类

package com.braintreepayments.browserswitch;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;

/**
 * <a href="https://developer.android.com/guide/topics/manifest/activity-element.html#lmode">singleTask</a>
 * Activity used to receive the response from a browser switch. This Activity contains no UI and
 * finishes during {@link Activity#onCreate(Bundle)}.
 */
public class BrowserSwitchActivity extends Activity {

    private static Uri sReturnUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        sReturnUri = null;
        if (getIntent() != null && getIntent().getData() != null) {
            sReturnUri = getIntent().getData();
        }

        finish();
    }

    /**
     * @return the uri returned from the browser switch, or {@code null}.
     */
    @Nullable
    public static Uri getReturnUri() {
        return sReturnUri;
    }

    /**
     * Clears the return uri.
     */
    public static void clearReturnUri() {
        sReturnUri = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我被困在如何从这个活动中获取上下文?

更新我已经更改了我的 python 代码,在我的 python 代码中使用此代码在 java 之外执行 DropInRequest.getIntent() 方法。

from jnius import autoclass
from jnius import cast
from android import activity
from kivy.context import get_current_context

context = autoclass('android.content.Context')
Intent = autoclass('android.content.Intent')
Uri = autoclass('android.net.Uri')
PythonActivity = autoclass('org.kivy.android.PythonActivity')

DropInRequest = autoclass('com.braintreepayments.api.dropin.DropInRequest')
BrowserSwitchActivity = autoclass('com.braintreepayments.api.BraintreeBrowserSwitchActivity')

#Global instance
instance = None
REQUEST = 1
RESULT_OK = 1

def onBraintreeSubmit(token):
    global instance

    def on_activity_result(request, response, data):
        global instance
        if request == REQUEST:
            print response
            if response == RESULT_OK:
                result = instance.getParcelableExtra(instance.EXTRA_DROP_IN_RESULT)
                nonce = result.getPaymentMethodNonce()
                print nonce
                return nonce

    currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
    context = cast('android.content.Context', currentActivity.getApplicationContext())
    activity.bind(on_activity_result=on_activity_result)
    instance = DropInRequest()
    instance.clientToken(token)
    mapintent = Intent()
    mapintent.setClassName(context,'com.braintreepayments.api.dropin.DropInRequest')
    mapintent.putExtra("com.braintreepayments.api.EXTRA_CHECKOUT_REQUEST","EXTRA_CHECKOUT_REQUEST")

    currentActivity.startActivityForResult(mapintent,REQUEST)
Run Code Online (Sandbox Code Playgroud)

并将其添加到我的清单中

<activity android:name="com.braintreepayments.api.dropin.DropInRequest" >
    </activity>
Run Code Online (Sandbox Code Playgroud)

我似乎正在取得进展,当我运行应用程序时,出现此错误。

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{org.test.myapp/com.braintreepayments.api.dropin.DropInRequest}: java.lang.ClassCastException: com.braintreepayments.api.dropin.DropInRequest cannot be cast to android.app.Activity
Run Code Online (Sandbox Code Playgroud)

我已经追溯了它,并且 DropInRequest 扩展了 Parcelable 而不是活动......

GoB*_*g06 6

要使用 pyjnius 创建上下文,您需要像这样投射它。

PythonActivity = autoclass('org.kivy.android.PythonActivity')
currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
context = cast('android.content.Context', currentActivity.getApplicationContext())
Run Code Online (Sandbox Code Playgroud)