chaquo / chaquopy

Chaquopy: the Python SDK for Android
https://chaquo.com/chaquopy/
MIT License
837 stars 133 forks source link

AttributeError: 'NoneType' object has no attribute 'getApplicationContext' #169

Closed SuhasSrikar closed 4 years ago

SuhasSrikar commented 4 years ago
W/python.stderr:   File "stdlib/threading.py", line 916, in _bootstrap_inner
      File "stdlib/threading.py", line 864, in run
W/python.stderr:   File "/data/user/0/com.works.python/files/chaquopy/AssetFinder/app/chaquopy/utils/console.py", line 14, in <lambda>
      File "class.pxi", line 695, in java.chaquopy.JavaMethod.__get__.lambda2
      File "class.pxi", line 715, in java.chaquopy.JavaMethod.__call__
      File "class.pxi", line 805, in java.chaquopy.JavaMethod.call_nonvirtual_method
      File "env.pxi", line 242, in java.chaquopy.CQPEnv.CallNonvirtualVoidMethodA
      File "env.pxi", line 484, in java.chaquopy.CQPEnv.check_exception
    com.chaquo.python.PyException: AttributeError: 'NoneType' object has no attribute 'getApplicationContext'
        at <python>.chaquopy.demo.repl.__init__(repl.py:11)
W/python.stderr:     at <python>.chaquopy_java.call(chaquopy_java.pyx:283)
D/AudioManager: getStreamVolume isRestricted mode = 0
W/python.stderr:     at <python>.chaquopy_java.Java_com_chaquo_python_PyObject_callAttrThrows(chaquopy_java.pyx:255)
        at com.chaquo.python.PyObject.callAttrThrows(Native Method)
        at com.chaquo.python.PyObject.callAttr(PyObject.java:207)
        at com.works.python.Activities.IDEActivity$Task.run(IDEActivity.java:51)
        at com.works.python.Activities.python.utils.ConsoleActivity$Task$1.run(ConsoleActivity.java:382)
mhsmith commented 4 years ago

The REPL code depends on App.context being set in App.onCreate:

https://github.com/chaquo/chaquopy/blob/24b8fbcdceb8070ab31205e67d87ead02124c794/app/src/main/java/com/chaquo/python/demo/App.java#L18-L20

Could you have changed anything which affects this?

SuhasSrikar commented 4 years ago

I haven't changed anything in App.java it's the same code. But in repl.py when I'm trying to handler the exception at InteractiveConsole the interpreter is opening fine but not giving any output

SuhasSrikar commented 4 years ago

This is my App.java file

package com.works.python.Activities;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.PreferenceManager;

import com.chaquo.python.android.PyApplication;

public class App extends PyApplication {

    public static final String DEFAULT_CHANNEL = "default";

    public static App context;
    public static SharedPreferences prefs;

    @Override
    public void onCreate() {
        super.onCreate();
        context = this;
        prefs = PreferenceManager.getDefaultSharedPreferences(this);

        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel channel = new NotificationChannel
                (DEFAULT_CHANNEL, "Default", NotificationManager.IMPORTANCE_LOW);
            ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                .createNotificationChannel(channel);
        }
    }

}

This is my repl.java file which I named it as IDEActivity.java

package com.works.python.Activities;

import android.app.Application;
import android.os.Bundle;
import android.text.InputType;
import android.widget.TextView;

import com.works.python.Activities.python.utils.PythonConsoleActivity;

public class IDEActivity extends PythonConsoleActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // VISIBLE_PASSWORD is necessary to prevent some versions of the Google keyboard from
        // displaying the suggestion bar.
        ((TextView) findViewById(resId("id", "etInput"))).setInputType(
                InputType.TYPE_CLASS_TEXT +
                        InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS +
                        InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);

    }

    @Override
    protected Class<? extends Task> getTaskClass() {
        return Task.class;
    }

    // Maintain REPL state unless the loop has been terminated, e.g. by typing `exit()`. Requires
    // the activity to be in its own task (see AndroidManifest).
    @Override
    public void onBackPressed() {
        if (task.getState() == Thread.State.RUNNABLE) {
            moveTaskToBack(true);
        } else {
            super.onBackPressed();
        }
    }

    // =============================================================================================

    public static class Task extends PythonConsoleActivity.Task {
        public Task(Application app) {
            super(app);
        }

        @Override
        public void run() {
            py.getModule("chaquopy.demo.repl")
                    .callAttr("AndroidConsole",App.context)
                    .callAttr("interact");
        }
    }

}

And this is repl.py

from __future__ import absolute_import, division, print_function

from code import InteractiveConsole
import sys

class AndroidConsole(InteractiveConsole):
    """`interact` must be run on a background thread, because it blocks waiting for input.
    """
    def __init__(self, context):
        InteractiveConsole.__init__(self, locals={"context": context.getApplicationContext()})

    def interact(self, banner=None):
        if banner is None:
            banner = ("Python {} on {}\n".format(sys.version, sys.platform) +
                      "The current application context is available in the variable 'context'.")
        try:
            InteractiveConsole.interact(self, banner)
        except SystemExit:
            pass
mhsmith commented 4 years ago

Your code looks fine, so I wonder whether App.context is actually being set in Java. Can you verify that using a debugger or a logcat call?

For example, if you changed either of the following things in AndroidManifest.xml:

... then App.onCreate might not be running anymore.

SuhasSrikar commented 4 years ago

I used Debugger to get the logs and here it is

 public static class Task extends PythonConsoleActivity.Task {
        public Task(Application app) {
            super(app);
        }

        @Override
        public void run() {
            py.getModule("chaquopy.demo.repl")
                    .callAttr("AndroidConsole",App.context)
                    .callAttr("interact");
            Log.i("Checking", "run: App.Context is called"); //checking if the above statements are executing

        }
    }

and these are the logs. Log is not executed

I/Timeline: Timeline: Activity_launch_request time:108313847 intent:Intent { cmp=com.works.python/.Activities.IDEActivity }
V/FA: Recording user engagement, ms: 7591
V/FA: Activity paused, time: 190838193
V/FA: onActivityCreated
D/FA: Logging event (FE): adunit_exposure(_xu), Bundle[{ga_event_origin(_o)=am, ad_unit_id(_ai)=ca-app-pub-2639216626142200/3956610047, ga_screen_class(_sc)=Home, ga_screen_id(_si)=-8629800055620022283, exposure_time(_xt)=4348}]
V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@f36dfb3
    BoostFramework() : mPerf = com.qualcomm.qti.Performance@9f7f970
V/FA: Not logging ad unit exposure. No active activity
    Not logging ad exposure. No active activity
I/art: Do partial code cache collection, code=249KB, data=240KB
I/art: After code cache collection, code=246KB, data=238KB
    Increasing code cache capacity to 1024KB
V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@ced21c4
    BoostFramework() : mPerf = com.qualcomm.qti.Performance@2d948ad
D/FA: Logging event (FE): ad_exposure(_xa), Bundle[{ga_event_origin(_o)=am, ga_screen_class(_sc)=Home, ga_screen_id(_si)=-8629800055620022283, exposure_time(_xt)=4348}]
W/python.stderr: Exception in thread Thread-1:
    Traceback (most recent call last):
W/python.stderr:   File "stdlib/threading.py", line 916, in _bootstrap_inner
      File "stdlib/threading.py", line 864, in run
      File "/data/user/0/com.works.python/files/chaquopy/AssetFinder/app/chaquopy/utils/console.py", line 14, in <lambda>
      File "class.pxi", line 695, in java.chaquopy.JavaMethod.__get__.lambda2
W/python.stderr:   File "class.pxi", line 715, in java.chaquopy.JavaMethod.__call__
      File "class.pxi", line 805, in java.chaquopy.JavaMethod.call_nonvirtual_method
      File "env.pxi", line 242, in java.chaquopy.CQPEnv.CallNonvirtualVoidMethodA
      File "env.pxi", line 484, in java.chaquopy.CQPEnv.check_exception
    com.chaquo.python.PyException: AttributeError: 'NoneType' object has no attribute 'getApplicationContext'
        at <python>.chaquopy.demo.repl.__init__(repl.py:11)
        at <python>.chaquopy_java.call(chaquopy_java.pyx:283)
W/python.stderr:     at <python>.chaquopy_java.Java_com_chaquo_python_PyObject_callAttrThrows(chaquopy_java.pyx:255)
        at com.chaquo.python.PyObject.callAttrThrows(Native Method)
        at com.chaquo.python.PyObject.callAttr(PyObject.java:207)
        at com.works.python.Activities.IDEActivity$Task.run(IDEActivity.java:52)
        at com.works.python.Activities.python.utils.ConsoleActivity$Task$1.run(ConsoleActivity.java:380)
W/python.stderr:  
D/FA: Logging event (FE): user_engagement(_e), Bundle[{ga_event_origin(_o)=auto, engagement_time_msec(_et)=7591, ga_screen_class(_sc)=Home, ga_screen_id(_si)=-8629800055620022283}]
V/FA: Activity resumed, time: 190838377
D/OpenGLRenderer: endAllActiveAnimators on 0xc1784880 (CardView) with handle 0xb6e26cf0
D/FA: Logging event (FE): screen_view(_vs), Bundle[{ga_event_origin(_o)=auto, ga_previous_class(_pc)=Home, ga_previous_id(_pi)=-8629800055620022283, ga_screen_class(_sc)=IDEActivity, ga_screen_id(_si)=-8629800055620022260}]
V/FA: Inactivity, disconnecting from the service
V/FA: Recording user engagement, ms: 30036
V/FA: Connecting to remote service
V/FA: Activity paused, time: 190868405
D/FA: Logging event (FE): user_engagement(_e), Bundle[{ga_event_origin(_o)=auto, engagement_time_msec(_et)=30036, ga_screen_class(_sc)=IDEActivity, ga_screen_id(_si)=-8629800055620022260}]
V/FA: Connection attempt already in progress
D/FA: Connected to remote service
V/FA: Processing queued up service tasks: 2
D/FA: Application backgrounded
D/FA: Logging event (FE): app_background(_ab), Bundle[{ga_event_origin(_o)=auto}]
V/FA: Inactivity, disconnecting from the service
SuhasSrikar commented 4 years ago

This is my Android Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.works.python">
<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true"
        android:name="com.chaquo.python.android.PyApplication">
SuhasSrikar commented 4 years ago

Oh I found out.

I changed the <application> in AndroidManifest

<application
        android:name="com.chaquo.python.android.PyApplication">

to

<application
        android:name=".Activities.App">

Which basically is

<application
        android:name=".App">

And it's working.!!!

Thank you @mhsmith . You made it easy for me to decode