在单独的应用程序中将 worker 的意图发送到 activity

Sending intents from a worker to an activity in a separate app

我有一个应用程序可以根据用户操作写入其本地存储;说的内容需要 被转发到另一个应用程序。

我的做法:

我不确定(也许需要打开一个单独的问题),但是在 activity 中创建的所有内容都会在 activity 停止时被销毁,对吗?这意味着添加工人,文件观察者的生命周期与他们定义的 activity 相同,对吗?

代码:

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final String FILE_OBSERVER_WORK_NAME = "file_observer_work";

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

        Log.i(TAG, "Creating file observer worker");
        WorkManager workManager = WorkManager.getInstance(getApplication());

        WorkContinuation continuation = workManager
                .beginUniqueWork(FILE_OBSERVER_WORK_NAME,
                        ExistingWorkPolicy.REPLACE,
                        OneTimeWorkRequest.from(APIWorker.class));

        Log.i(TAG, "Starting worker");
        continuation.enqueue();

        final Button button = findViewById(R.id.button2);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Log.i(TAG, "Button clicked!");

                String stuffToWriteToFile = getStuff();
                String cwd = getApplicationInfo().dataDir;
                String stuffFilePath= cwd + File.separator + "stuff.json";

                PrintWriter stuffFile= null;
                try {
                    stuffFile = new PrintWriter(stuffFilePath, "UTF-8");
                    stuffFile.println(stuffToWriteToFile);
                    stuffFile.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void onResume(){
        super.onResume();
        // start worker here?
    }

    @Override
    public void onStart() {
        super.onStart();
    // start worker here?
    }
}

APIWorker.java: public class APIWorker 扩展 Worker {

    public APIWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    private static final String TAG = APIWorker.class.getSimpleName();

    @NonNull
    @Override
    public Result doWork() {
        Context applicationContext = getApplicationContext();
        Log.d(TAG, "Observing stuff file");

        FileObserver fileObserver = new FileObserver(cwd) {
            @Override
            public void onEvent(int event, @Nullable String path) {
                if(event == FileObserver.CREATE ||
                   event == FileObserver.MODIFY) {

                    String cwd = applicationContext.getApplicationInfo().dataDir;
                    String stuffFilePath = cwd + File.separator + "stuff.json";

                    String fileContents;
                    File observedFile = new File(stuffFilePath);
                    long length = observedFile.length();
                    if (length < 1 || length > Integer.MAX_VALUE) {
                        fileContents = "";
                        Log.w(TAG, "Empty file: " + observedFile);
                    } else {
                        try (FileReader in = new FileReader(observedFile)) {
                            char[] content = new char[(int)length];

                            int numRead = in.read(content);
                            if (numRead != length) {
                                Log.e(TAG, "Incomplete read of " + observedFile +
                                        ". Read chars " + numRead + " of " + length);
                            }
                            fileContents = new String(content, 0, numRead);

                            Log.d(TAG, "Sending intent ");
                            String packageName = "com.cam.differentapp";
                            Intent sendIntent = applicationContext.getPackageManager().
                                    getLaunchIntentForPackage(packageName);
                            if (sendIntent == null) {
                                // Bring user to the market or let them choose an app?
                                sendIntent = new Intent(Intent.ACTION_VIEW);
                                sendIntent.setData(Uri.parse("market://details?id=" + packageName));
                            }
                            // sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            sendIntent.setAction(Intent.ACTION_SEND);
                            sendIntent.putExtra(Intent.EXTRA_TEXT, fileContents);
                            sendIntent.setType("application/json");

                            applicationContext.startActivity(sendIntent);

                            Log.d(TAG, "Intent sent ");
                        }
                        catch (Exception ex) {
                            Log.e(TAG, "Failed to read file " + path, ex);
                            fileContents = "";
                        }
                    }
                }
            }
        };

        fileObserver.startWatching();

        return null;
    }
}

查看文档:

https://developer.android.com/guide/components/activities/background-starts

对于何时可以从后台启动活动有限制,但也有例外,即:

The app has a visible window, such as an activity in the foreground.

意思是(我认为?)只要用户与应用程序 (MainActivity) 交互,后台工作程序就应该 运行,对吗?如果 activity 是 paused/destroyed 就停止了,对吗?

如果您有后台处理不需要用户交互(显示或用户输入),通常您会使用 Service。如果您的应用程序在前台,那么您的 Service 可以使用 startActivity().

启动其他活动

我觉得你的架构很奇怪。您使用的是 Worker,它的生命周期最长为 10 分钟。您正在启动 Worker,然后创建一个 FileObserver 来检测 creation/modification 个文件。然后它读取文件并启动另一个 Activity。这是一种非常复杂和迂回的做事方式。我怀疑你能否使它可靠地工作。

您的 Activity 正在将数据写入文件系统。它可以在写入文件后调用一个方法(在后台线程上),然后将数据转发到另一个 Activity。这会更直接,并且移动部件更少。

我不知道 Activity 的生命周期如何影响 Worker。我假设它们没有直接链接到 Activity,因此不会在 Activity 暂停或销毁时停止。

我还注意到您正在主线程 (UI) 上写入文件(在您的 OnClickListener 中)。这不行,您应该在后台线程中执行文件 I/O,因为文件 I/O 可能会阻塞,而您不想阻塞主线程 (UI)。