简体   繁体   English

如何在Android中实现模拟活动识别

[英]How to implement mock activity Recognition in android

I am creating a framework which will test the android application. 我正在创建一个框架,它将测试android应用程序。 In the android application they have implemented Activity Recognition to know the user activity. 在android应用程序中,他们已经实现了Activity Recognition来了解用户活动。 I want to test the functionality in a framework. 我想测试框架中的功能。 Can anybody tell me how to implement mock activity recognition in android? 有人可以告诉我如何在android中实现模拟活动识别吗?

Thanks 谢谢

I would advice you to subclass the ActivityRecognitionClient and reimplement methods which handle registration to updates and take there the reference to the pending intent which calls your subclassed ActivityRecognitionIntentService . 我建议您将ActivityRecognitionClient和reimplement方法子类化,后者处理更新注册,并在其中引用对调用您的子类ActivityRecognitionIntentService的暂挂意图的引用。

You can then periodically call your service with some artificial data..How to call it? 然后,您可以定期使用一些人工数据调用服务。如何调用它? I would just use a thread with handler for its simplicity. 我只是使用带有处理程序的线程来简化它。

EDIT: I have added a very abstract code snippet which should give you the idea.. 编辑:我添加了一个非常抽象的代码片段,应该可以给您这个主意。

    public class MainActivity extends FragmentActivity implements
        ConnectionCallbacks, OnConnectionFailedListener {

    private ActivityRecognitionClient mActivityRecognitionClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

            mActivityRecognitionClient = MOCK ? new MockActivityRecognitionClient(getApplicationContext(), this, this) : new ActivityRecognitionClient(getApplicationContext(), 
            this, this);
    }        
    ...
    /*
     * Called by Location Services once the location client is connected.
     *
     * Continue by requesting activity updates.
     */
    @Override
    public void onConnected(Bundle dataBundle) {
        /*
         * Request activity recognition updates using the preset
         * detection interval and PendingIntent. This call is
         * synchronous.
         */
        mActivityRecognitionClient.requestActivityUpdates(
                DETECTION_INTERVAL_MILLISECONDS,
                mActivityRecognitionPendingIntent);
        /*
         * Since the preceding call is synchronous, turn off the
         * in progress flag and disconnect the client
         */
        mInProgress = false;
        mActivityRecognitionClient.disconnect();
    }
    ...
}


/**
 * Service that receives ActivityRecognition updates. It receives
 * updates in the background, even if the main Activity is not visible.
 */
public class ActivityRecognitionIntentService extends IntentService {
    ...
    /**
     * Called when a new activity detection update is available.
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        ...
    }
    ...
}


public class MockActivityRecognitionClient extends ActivityRecognitionClient {

    private List<ConnectionCallbacks> mConnectionCallbacksList;
    private List<OnConnectionFailedListener> mConnectionFailedListenerlist;
    private final Handler mHandler;
    private long interval = 1000; //default 1000ms
    private PendingIntent mPendingIntent;
    private Context mContext;

    public MockActivityRecognitionClient(Context context, ConnectionCallbacks connectedListener, OnConnectionFailedListener connectionFailedListener) {
        super(context, connectedListener, connectionFailedListener);
        registerConnectionCallbacks(connectedListener);
        registerConnectionFailedListener(connectionFailedListener);
        mHandler = new Handler(Looper.getMainLooper());
        mContext = context;

    }

    @Override
    public void requestActivityUpdates(long detectionIntervalMillis, PendingIntent callbackIntent) {
        interval = detectionIntervalMillis;
        mPendingIntent = callbackIntent;
        mHandler.postDelayed(postLocationUpdateRunnable, interval);
    }

    @Override
    public void removeActivityUpdates(PendingIntent callbackIntent) {
        mHandler.removeCallbacks(postLocationUpdateRunnable);
    }

    @Override
    public void connect() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                postConnected();
            }
        }, 2000);
    }

    private void postConnected() {
        for(ConnectionCallbacks connectionCallbacks : mConnectionCallbacksList){
            connectionCallbacks.onConnected(new Bundle()); //insert mocku bundle data
        }
    }

    @Override
    public boolean isConnected() {

    }

    @Override
    public boolean isConnecting() {

    }

    @Override
    public void registerConnectionCallbacks(ConnectionCallbacks listener) {
            if(mConnectionCallbacksList == null){
                mConnectionCallbacksList = new LinkedList<>();
            }
        mConnectionCallbacksList.add(listener);
    }

    @Override
    public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) {
        return mConnectionCallbacksList.contains(listener);
    }

    @Override
    public void unregisterConnectionCallbacks(ConnectionCallbacks listener) {
        mConnectionCallbacksList.remove(listener);
    }

    @Override
    public void registerConnectionFailedListener(OnConnectionFailedListener listener) {
        ...
    }

    @Override
    public boolean isConnectionFailedListenerRegistered(OnConnectionFailedListener listener) {
        ...
    }

    @Override
    public void unregisterConnectionFailedListener(OnConnectionFailedListener listener) {
        ...
    }

    @Override
    public void disconnect() {

    }

    private final Runnable postLocationUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            try {
                mPendingIntent.send(mContext, 1234, new Intent()); // in the intent should probably be the mocked activity data - I dont know the exact structure, it should be documented
            } catch (PendingIntent.CanceledException e) {
                e.printStackTrace();
            }
            mHandler.postDelayed(this, interval);
        }
    };
}    

You can check this code, This is also include how you can get location of user when particular activity occurs. 您可以检查此代码,这还包括在发生特定活动时如何获取用户的位置。

MainActivity 主要活动

class MainActivity : AppCompatActivity(), GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
    override fun onConnected(p0: Bundle?) {
        requestActivityUpdates()
    }
    override fun onConnectionSuspended(p0: Int) {
        Log.e("location", "connection suspended, retry to connect")
        apiClient.connect()
    }
    override fun onConnectionFailed(p0: ConnectionResult) {
        Log.e("location", "connection error ${p0.errorMessage}")
    }
    lateinit var apiClient: GoogleApiClient
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        init()
    }
    override fun onStart() {
        super.onStart()
        apiClient.connect()
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_COARSE_LOCATION), 100)
        }
    }
    override fun onStop() {
        super.onStop()
        if (apiClient.isConnected)
            apiClient.disconnect()
    }
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            100 -> {
                if (grantResults.isNotEmpty() && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this, "You must assign permission of your location", Toast.LENGTH_SHORT).show()
                    finish()
                }
            }
        }
    }
    private fun init() {
        apiClient = GoogleApiClient.Builder(this).addApi(ActivityRecognition.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build()
    }
    fun requestActivityUpdates() {
        if (!apiClient.isConnected) {
            Toast.makeText(this, "GoogleApiClient not yet connected", Toast.LENGTH_SHORT).show()
        } else {
            ActivityRecognition.getClient(this).requestActivityUpdates(0, getActivityDetectionPendingIntent())
        }
    }
    fun removeActivityUpdates() {
        ActivityRecognition.getClient(this).removeActivityUpdates(getActivityDetectionPendingIntent())
    }
    private fun getActivityDetectionPendingIntent(): PendingIntent {
        val intent = Intent(this, ActivityRecognizeService::class.java)
        return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }
}

Service 服务

class ActivityRecognizeService : IntentService("LjRecognize") {

    lateinit var location: Location
    private var fusedLocationClient: FusedLocationProviderClient? = null

    override fun onHandleIntent(intent: Intent?) {
        if (intent == null)
            return

        if (ActivityRecognitionResult.hasResult(intent)) {
            val result = ActivityRecognitionResult.extractResult(intent)
            val time = System.currentTimeMillis()
            result.probableActivities.forEach {
                when (it.type) {
                    DetectedActivity.IN_VEHICLE -> {
                        Log.e("Activity found", "on vehicle at " + time + " with confidence of " + it.confidence)
                    }

                    DetectedActivity.ON_BICYCLE -> {
                        Log.e("Activity found", "on bicycle at " + time + " with confidence of " + it.confidence)
                    }

                    DetectedActivity.ON_FOOT -> {
                        Log.e("Activity found", "on foot at " + time + " with confidence of " + it.confidence)
                        getLocation()
                    }

                    DetectedActivity.STILL -> {
                        Log.e("Activity found", "still at " + time + " with confidence of " + it.confidence)
                    }

                    DetectedActivity.UNKNOWN -> {
                        Log.e("Activity found", "unknown at " + time + " with confidence of " + it.confidence)
                    }

                    DetectedActivity.TILTING -> {
                        Log.e("Activity found", "tilted at " + time + " with confidence of " + it.confidence)
                    }
                }
            }
        }
    }

    private fun getLocation() {
        if (fusedLocationClient == null)
            fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)

        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            fusedLocationClient!!.lastLocation.addOnSuccessListener {
                if (it != null)
                    location = it

                Log.e("location", "found -> lat: ${location.latitude}, lng: ${it.longitude}")
            }
        } else {
            startActivity(Intent(this, MainActivity::class.java))
        }
    }
}

Don't forgot to add permissions 不要忘记添加权限

<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM