Jim Ng
Jim Ng

Reputation: 101

How do I solve Could not find method in a parent or ancestor Context for android:onClick attribute?

I am trying to launch a foreground service and notification when the user clicks on a button. This button is called "startBtn". It is meant to show the number of steps that the user takes.

I have 3 files, StepsFragment.java, fragment_steps.xml and StepsService.java.

I encountered this error in Logcat when the user clicks on the button:

java.lang.IllegalStateException: Could not find method startService(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatButton with id 'startBtn'

I have tried these following solutions asked on StackOverflow:

How to solve error: Could not find method onClick(View) in a parent or ancestor Context for android:onClick

Could not find method in a parent or ancestor Context for android:onClick attribute

This is my code in StepsFragment.java:

package sg.edu.singaporetech.teamproject;

import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class StepsFragment extends Fragment implements SensorEventListener, View.OnClickListener {

    Button updateBtn;
    ProgressBar progressBar;
    TextView tv_steps;
    TextView levelDisplay;
    SensorManager sensorManager;
    Sensor sensor;
    boolean running = false;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {


        View view = inflater.inflate(R.layout.fragment_steps, container, false);

        super.onCreate ( savedInstanceState );
        updateBtn = view.findViewById(R.id.updateBtn);
        progressBar = view.findViewById(R.id.progress_bar);
        tv_steps = (TextView) view.findViewById(R.id.tv_steps);
        levelDisplay = (TextView) view.findViewById(R.id.levelDisplay);
        sensorManager = (SensorManager) getActivity().getSystemService ( Context.SENSOR_SERVICE);

        updateBtn.setOnClickListener(this);

        return view;

    }

    public void startService(View view) {
        String input = tv_steps.getText().toString();
        Intent serviceIntent = new Intent(getActivity(),StepsService.class);
        serviceIntent.putExtra("inputExtra",input);

        getActivity().startService(serviceIntent);
    }

}

This is the button code in fragment_steps.xml:

    <android.support.v7.widget.AppCompatButton
        android:id="@+id/startBtn"
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:background="@drawable/btn_orange"
        android:text="@string/start_steps"
        android:textColor="@color/white"
        android:textSize="15dp"
        android:onClick="startService"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/updateBtn" />

And lastly, this is the code in StepsService.java

package sg.edu.singaporetech.teamproject;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;

import static sg.edu.singaporetech.teamproject.StepsNotification.CHANNEL_ID;

public class StepsService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String input = intent.getStringExtra("inputExtra");

        Intent notificationIntent = new Intent(this,StepsFragment.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("Steps Tracker")
                .setContentText("Steps tracked")
                .setSmallIcon(R.drawable.exersize)
                .setContentIntent(pendingIntent)
                .build();
        startForeground(1,notification);

        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Upvotes: 1

Views: 2741

Answers (1)

John Joe
John Joe

Reputation: 12803

android:onClick="startService" will not called in fragment. You should use OnClickListener instead to handle this type of events.

Another approach is declare the startService function in activity, then call the fragment method from the activity.

Kindly refer Android app crashing (fragment and xml onclick) to know more.

Upvotes: 3

Related Questions