为 android 响应本机剪贴板侦听器服务

时间:2021-01-20 09:46:04

标签: android react-native performance react-native-android

我正在使用 React Native 开发一个应用程序。当我的应用程序在后台运行或已终止时,我正在搜索代码。我想要一个像 notifcationListnerService 这样的服务来再次调用该应用程序。想要一个始终运行的类似服务,当用户复制某些内容时,它会向用户显示推送通知,就像您复制了某些内容一样。 这是我尝试过的,但这些太复杂而无法理解,因为这些是在 Java 中。

Android ClipBoard Manager

Android ClipBoard With Example

This question from StackOverflow also does not have any answer

A solution for GitHub but too complex

不需要的东西 @react-native-community/clipboard 或类似的东西。我需要的是在为设备上安装的任何应用复制某些内容时显示推送通知

1 个答案:

答案 0 :(得分:1)

所以终于搜索了两天终于实现了我想要的。我展示的是祝酒词,而不是通知(稍后会实施)。我正在共享我的代码,但是当我的应用程序重新启动剪贴板管理器的服务时,我遇到了问题,该服务正在运行,正如我在 logcat 中看到的那样。这是我的代码。

ClipboardMonitorService.java

    package com.wm;
    import android.app.Service;
    import android.content.ClipData;
    import android.content.ClipboardManager;
    import android.content.Intent;
    import android.os.Environment;
    import android.os.IBinder;
    import android.text.TextUtils;
    import android.util.Log;
    import android.widget.Toast;
    
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.Date;
    public class ClipboardMonitorService extends Service {
        private static final String TAG = "ClipboardManager";
        private static final String FILENAME = "clipboard-history.txt";
    
        private File mHistoryFile;
        private ExecutorService mThreadPool = Executors.newSingleThreadExecutor();
        private ClipboardManager mClipboardManager;
    
        @Override
        public void onCreate() {
            super.onCreate();
                Log.e("service is running","service is running");
            // TODO: Show an ongoing notification when this service is running.
            mHistoryFile = new File(getExternalFilesDir(null), FILENAME);
            mClipboardManager =
                    (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
            mClipboardManager.addPrimaryClipChangedListener(
                    mOnPrimaryClipChangedListener);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
    
            if (mClipboardManager != null) {
                mClipboardManager.removePrimaryClipChangedListener(
                        mOnPrimaryClipChangedListener);
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        private boolean isExternalStorageWritable() {
            String state = Environment.getExternalStorageState();
            if (Environment.MEDIA_MOUNTED.equals(state)) {
                return true;
            }
            return false;
        }
    
        private ClipboardManager.OnPrimaryClipChangedListener mOnPrimaryClipChangedListener =
                new ClipboardManager.OnPrimaryClipChangedListener() {
                    @Override
                    public void onPrimaryClipChanged() {
                        Log.d(TAG, "onPrimaryClipChanged");
                        ClipData clip = mClipboardManager.getPrimaryClip();
                        mThreadPool.execute(new WriteHistoryRunnable(clip.getItemAt(0).getText()));
                        Log.e("Copied Text","hahah"+clip.getItemAt(0).getText());
                        Toast.makeText(getApplicationContext(),"My App toast",Toast.LENGTH_SHORT).show();
                    }
                };
    
        private class WriteHistoryRunnable implements Runnable {
            private final Date mNow;
            private final CharSequence mTextToWrite;
    
            public WriteHistoryRunnable(CharSequence text) {
                mNow = new Date(System.currentTimeMillis());
                mTextToWrite = text;
            }
    
            @Override
            public void run() {
                if (TextUtils.isEmpty(mTextToWrite)) {
                    // Don't write empty text to the file
                    return;
                }
    
                if (isExternalStorageWritable()) {
                    try {
                        Log.i(TAG, "Writing new clip to history:");
                        Log.i(TAG, mTextToWrite.toString());
                        BufferedWriter writer =
                                new BufferedWriter(new FileWriter(mHistoryFile, true));
                        writer.write(String.format("[%s]: ", mNow.toString()));
                        writer.write(mTextToWrite.toString());
                        writer.newLine();
                        writer.close();
                    } catch (IOException e) {
                        Log.w(TAG, String.format("Failed to open file %s for writing!",
                                mHistoryFile.getAbsoluteFile()));
                    }
                } else {
                    Log.w(TAG, "External storage is not writable!");
                }
            }
        }
    }

这用于当应用程序关闭或设备重新启动时,它将再次启动服务。 BootUpRecever.java

    package com.wm;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Build;
    
    public class BootUpReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction() == Intent.ACTION_BOOT_COMPLETED){
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    //log("Starting the service in >=26 Mode from a BroadcastReceiver")
                    context.startForegroundService(new Intent(context, ClipboardMonitorService.class));
                    return;
                }
                //log("Starting the service in < 26 Mode from a BroadcastReceiver")
                context.startService(new Intent(context, ClipboardMonitorService.class));
            }
    
        }
    }

在应用启动时启动活动
MainActivity.java

      package com.wm;
  
  import android.content.Intent;
  import android.os.Bundle;
  
  import com.facebook.react.ReactActivity;
  public class MainActivity extends ReactActivity {
  
    @Override
    protected String getMainComponentName() {
      return "wm";
    }
  
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
      super.onCreate(savedInstanceState);
  
      // TODO: Show the contents of the clipboard history.
      startService(new Intent(this, ClipboardMonitorService.class));
  
    }
  }

这里是权限和启动服务 AndroidManifest.xml

        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.wm">
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
        <uses-permission android:name="android.permission.READ_CONTACTS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
        <application
          android:name=".MainApplication"
          android:label="@string/app_name"
          android:icon="@mipmap/ic_launcher"
          android:roundIcon="@mipmap/ic_launcher_round"
          android:allowBackup="true"
          android:theme="@style/AppTheme">
          <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
            android:launchMode="singleTask"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
          </activity>
          <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
            <service
                android:name=".ClipboardMonitorService"
                android:label="Clipboard Monitor"
                android:exported="false"/>
            <receiver
                android:name=".BootUpReceiver"
                android:enabled="true"
                android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </receiver>
            
        </application>
    
    </manifest>