Android: 如何从服务中调用方法

Android: How to call a method from a Service

我正在制作一个应用程序,它从 phone 读取短信并将短信从特定发件人发送到服务器。我想使用服务在后台应用 运行,但它不起作用。当我尝试启动服务时,应用程序崩溃了。

(如果我使用 Mediaplayer 播放一些音乐,服务工作正常,但我认为当我尝试 运行 sendingData() 服务启动时调用的方法存在一些问题)

相关代码如下:

MainActivity.java

package com.example.texter;

import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    private static MainActivity inst;
    ArrayList<String> smsMessagesList = new ArrayList<String>();
    ListView smsListView;
    ArrayAdapter arrayAdapter;
    Timer timer;
    static String smssender;
    Button stopButton;
    Button startButton;
    static String content;

    public static MainActivity instance() {
        return inst;
    }
    @Override
    public void onStart() {
        super.onStart();
        inst = this;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        smsListView = (ListView) findViewById(R.id.SMSlist);

        startButton = (Button) findViewById(R.id.button2);
        stopButton = (Button) findViewById(R.id.stopbtn);

        arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, smsMessagesList);
        smsListView.setAdapter(arrayAdapter);

        // Todo : If Permission Is Not GRANTED
        if(ContextCompat.checkSelfPermission(getBaseContext(), "android.permission.READ_SMS") == PackageManager.PERMISSION_GRANTED) {

            // Todo : If Permission Granted Then Show SMS
            refreshSmsInbox();

        } else {
            // Todo : Then Set Permission
            final int REQUEST_CODE_ASK_PERMISSIONS = 123;
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{"android.permission.READ_SMS"}, REQUEST_CODE_ASK_PERMISSIONS);
            Toast.makeText(this, "Please allow permissions to read SMS", Toast.LENGTH_SHORT).show();
        }

        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Intent intent = new Intent(MainActivity.this, MainActivity.class);
                overridePendingTransition(0, 0);     //to avoid blinking on refresh
                startActivity(intent);
                overridePendingTransition(0, 0);

            }
        }, 10000);

    }

    public void refreshSmsInbox() {

        ContentResolver contentResolver = getContentResolver();
        Cursor smsInboxCursor = contentResolver.query(Uri.parse("content://sms/inbox"), null, null, null, null);
        int indexBody = smsInboxCursor.getColumnIndex("body");
        int indexAddress = smsInboxCursor.getColumnIndex("address");
        if (indexBody < 0 || !smsInboxCursor.moveToFirst()) return;
        arrayAdapter.clear();
        do {
            String str = "SMS From: " + smsInboxCursor.getString(indexAddress) +
                    "\n" + smsInboxCursor.getString(indexBody) + "\n";
            arrayAdapter.add(str);

        } while (smsInboxCursor.moveToNext());

        smsInboxCursor.moveToFirst();
        if (smsInboxCursor.getString(indexAddress).equalsIgnoreCase("JX-JioSvc")) {
            //NOW SEND TO SERVER
            Toast.makeText(MainActivity.this,"Yes, JX-JioSvc", Toast.LENGTH_SHORT).show();
            content = smsInboxCursor.getString(indexBody);
            this.sendingData();

        }
        else {
            Toast.makeText(MainActivity.this, "No, JX-JioSvc", Toast.LENGTH_SHORT).show();
        }

    }

    public void updateList(final String smsMessage) {
        arrayAdapter.insert(smsMessage, 0);
        arrayAdapter.notifyDataSetChanged();
    }

    public void sendingData() {
        String url = "---IP HERE---";
        StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Toast.makeText(MainActivity.this, response.trim(), Toast.LENGTH_LONG).show();
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(MainActivity.this, error.toString(), Toast.LENGTH_LONG).show();
                    }
                }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put("data", content);

                return params;
            }
        };

        RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
        requestQueue.add(stringRequest);

    }

    public void startService(View view) {
        startService(new Intent(this, Service.class));
    }

    public void stopService(View view) {
        stopService(new Intent(this, Service.class));
    }
}

Service.java

package com.example.texter;

import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

import androidx.annotation.Nullable;

public class Service extends android.app.Service {


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();

        MainActivity object = new MainActivity();
        object.sendingData();

        return START_STICKY;
    }
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
    }

}

我们不应该创建 MainActivity 对象来调用 API.Instead 从 Main 创建本地广播 Activity 并注册要调用的 broadcast.When API,发送广播到MainActivity即可触发API.For创建本地广播,可查看下方link.

How to use LocalBroadcastManager?