开机时将位置发送到Google表单(如何在启动时运行MainActivity)

3

所以我在Android Studio方面基本上是个初学者,但我已经接近成功了。我的目标是将经度、纬度和一些其他数据传输到google上的一个表单中。当我按下按钮(button2)时它可以正常工作,但我想让它在启动时自动开始发送数据的活动。所以我写了一个bootreceiver,但它只能启动应用程序而不能启动发送数据的活动。希望有人可以帮帮我。如果有不清楚的地方,请问。

MyService.java:

package com.test.example.phonelocationnew;

import android.app.Service;
import android.content.Intent;
import android.view.View;
import android.widget.Toast;
import android.os.IBinder;

public class MyService extends Service
{
@Override
public void onCreate(){

}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
    Toast.makeText(this, "Service started...", Toast.LENGTH_LONG).show();
    return START_STICKY;
}

@Override
public void onDestroy()
{
    super.onDestroy();
    Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
}
@Override
public IBinder onBind(Intent intent) {
    return null;
}
}

BootReceiver.java:

package com.test.example.phonelocationnew;

import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.Intent;

public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

    if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
        Intent serviceIntent = new Intent(context, MyService.class);
        context.startService(serviceIntent);
    }
}
}

MainActivity.java:

    package com.test.example.phonelocationnew;

import android.Manifest;
import android.content.res.Configuration;
import android.location.GpsSatellite;
import android.os.AsyncTask;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.telephony.TelephonyManager;
import android.widget.Button;
import android.widget.Toast;


import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;

import android.view.View;
import android.widget.TextView;

import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import java.net.*;
import java.util.concurrent.TimeUnit;


public class MainActivity extends Activity implements LocationListener{

    public static final MediaType FORM_DATA_TYPE = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
    //URL derived from form URL
    public static final String URL = "URL";
    //input element ids found from the live form page
    public static final String LAT="entry_1903202747";
    public static final String LONG="entry_1549783406";
    public static final String MOD="entry_1161588883";
    public static final String MAN="entry_852582911";
    public static final String IMEI="entry_738564261";
    public static final String EXIP="entry_1256979126";
    public static final String ACC="entry_1601482207";


    private Context context;

    LocationManager locationmanager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout);
        context=this;

        Intent intent = new Intent(this, MyService.class);
        startService(intent);

        Button button2 = (Button)findViewById(R.id.button2);

        final TextView textView3 = (TextView) findViewById(R.id.textView3);
        final TextView textView5 = (TextView) findViewById(R.id.textView5);
        final TextView textView12 = (TextView) findViewById(R.id.textView12);
        final TextView textView13 = (TextView) findViewById(R.id.textView13);
        final TextView textView14 = (TextView) findViewById(R.id.textView14);
        final TextView textView7 = (TextView) findViewById(R.id.textView7);
        final TextView textView15 = (TextView) findViewById(R.id.textView15);



        locationmanager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Criteria cri = new Criteria();
        String provider = locationmanager.getBestProvider(cri, false);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0);
        }

        if (provider != null & !provider.equals("")) {
            Location location = locationmanager.getLastKnownLocation(provider);
            locationmanager.requestLocationUpdates(provider, 30000, 0, this); //original (provider,minimalTime,minimalDistance,this); (provider,1800000,0,this) = 30 minutes; 0 distance change

            if (location != null) {
                onLocationChanged(location);
            } else {
                Toast.makeText(getApplicationContext(), "location not found", Toast.LENGTH_LONG).show();
            }
        } else {
            Toast.makeText(getApplicationContext(), "Provider is null", Toast.LENGTH_LONG).show();
        }

    }


    @Override
    public void onLocationChanged(Location location) {

        TextView textView3 = (TextView) findViewById(R.id.textView3);
        TextView textView5 = (TextView) findViewById(R.id.textView5);
        TextView textView12 = (TextView) findViewById(R.id.textView12);
        TextView textView13 = (TextView) findViewById(R.id.textView13);
        TextView textView14 = (TextView) findViewById(R.id.textView14);
        TextView textView7 = (TextView) findViewById(R.id.textView7);
        TextView textView15 = (TextView) findViewById(R.id.textView15);


        TelephonyManager mngr = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);

        String strLat="LA "+location.getLatitude();
        String strLong="LO "+location.getLongitude();
        String strAcc=""+location.getAccuracy();
        String strMod=""+ Build.MODEL;
        String strMan=""+ Build.MANUFACTURER;
        String strId=""+ mngr.getDeviceId();

        try{
            URL whatismyip = new URL("http://checkip.amazonaws.com/");
            BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));

            String ip = in.readLine(); //you get the IP as a String
            String strIp =""+ip;
            textView7.setText(strIp);
        }catch(Exception ex) {
            textView7.setText("ERROR");
        }

        textView3.setText(strLat);
        textView5.setText(strLong);
        textView12.setText(strMod);
        textView13.setText(strMan);
        textView14.setText(strId);
        textView15.setText(strAcc);

        final PostDataTask postDataTask = new PostDataTask();
        postDataTask.execute(URL, textView3.getText().toString(), textView5.getText().toString(), textView12.getText().toString(), textView13.getText().toString(), textView14.getText().toString(), textView7.getText().toString(), textView15.getText().toString());

    }

    //Start Service
    public void startService(View view){
        Intent intent = new Intent(this,MyService.class);
        startService(intent);
    }
    //Stop Service
    public void stopService(View view){
        Intent intent = new Intent(this,MyService.class);
        stopService(intent);
    }
    @Override
    public void onStatusChanged(String s, int i, Bundle bundle){
    }

    @Override
    public void onProviderEnabled(String s){
    }

    @Override
    public void onProviderDisabled(String s){
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.layout);
    }

    //AsyncTask to send data as a http POST request
    private class PostDataTask extends AsyncTask<String, Void, Boolean> {

        @Override
        protected Boolean doInBackground(String... contactData) {

            Boolean result = true;
            String url = contactData[0];
            String LATs = contactData[1];

            String LONGs = contactData[2];
            String modS = contactData[3];
            String manS = contactData[4];
            String idS = contactData[5];
            String ipS = contactData[6];
            String accS = contactData[7];

            String postBody="";

            try {
                //all values must be URL encoded to make sure that special characters like & | ",etc.
                //do not cause problems
                postBody = LAT + "=" + URLEncoder.encode(LATs,"UTF-8") +
                        "&" + LONG + "=" + URLEncoder.encode(LONGs,"UTF-8") +
                        "&" + MOD + "=" + URLEncoder.encode(modS,"UTF-8") +
                        "&" + MAN + "=" + URLEncoder.encode(manS,"UTF-8") +
                        "&" + IMEI + "=" + URLEncoder.encode(idS,"UTF-8") +
                        "&" + EXIP + "=" + URLEncoder.encode(ipS,"UTF-8") +
                        "&" + ACC + "=" + URLEncoder.encode(accS,"UTF-8");
            } catch (UnsupportedEncodingException ex) {
                result=false;
            }

            try{
                //Create OkHttpClient for sending request
                OkHttpClient client = new OkHttpClient();
                //Create the request body with the help of Media Type
                RequestBody body = RequestBody.create(FORM_DATA_TYPE, postBody);
                Request request = new Request.Builder()
                        .url(url)
                        .post(body)
                        .build();
                //Send the request
                Response response = client.newCall(request).execute();
            }catch (IOException exception){
                result=false;
            }
            return result;
        }

        @Override
        protected void onPostExecute(Boolean result){
            //Print Success or failure message accordingly
//            try {
//                Thread.sleep(1800000);
//            } catch(InterruptedException ex) {
//                Thread.currentThread().interrupt();
//            }
            Toast.makeText(context,result?"Message successfully sent!":"There was some error in sending message. Please try again after some time.",Toast.LENGTH_LONG).show();
        }

    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.example.phonelocationnew" >

    <uses-permission android:name="android.permission.INTERNET"/>
    <!--<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <uses-sdk  android:maxSdkVersion="21"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:configChanges="keyboardHidden|orientation">

        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver
            android:name=".BootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>

        </receiver>

        <service android:name=".MyService" />

    </application>

</manifest>

Layout.xml:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    android:background="#620606"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:nestedScrollingEnabled="false">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Latitude = "
        android:id="@+id/textView"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:id="@+id/textView3"
        android:layout_alignTop="@+id/textView"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:text="..." />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Longtitude = "
        android:id="@+id/textView4"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:layout_below="@+id/textView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:id="@+id/textView5"
        android:layout_alignTop="@+id/textView4"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:text="..." />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop Service"
        android:id="@+id/button"
        android:onClick="stopService"
        android:layout_gravity="center_horizontal"
        android:backgroundTint="#3b2525"
        android:textColor="#ffffff"
        android:layout_alignTop="@+id/button2"
        android:layout_toRightOf="@+id/button2"
        android:layout_toEndOf="@+id/button2" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Service"
        android:onClick="startService"
        android:id="@+id/button2"
        android:backgroundTint="#3b2525"
        android:textColor="#ffffff"
        android:layout_alignParentBottom="true"
        android:layout_toRightOf="@+id/textView11"
        android:layout_toEndOf="@+id/textView11" />


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Model = "
        android:id="@+id/textView9"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:layout_below="@+id/textView8"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Manufacturer = "
        android:id="@+id/textView10"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:layout_below="@+id/textView9"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="IMEI = "
        android:id="@+id/textView11"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:layout_below="@+id/textView10"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="..."
        android:id="@+id/textView12"
        android:layout_above="@+id/textView10"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="..."
        android:id="@+id/textView13"
        android:layout_alignBottom="@+id/textView10"
        android:layout_alignRight="@+id/textView12"
        android:layout_alignEnd="@+id/textView12" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="..."
        android:id="@+id/textView14"
        android:layout_alignTop="@+id/textView11"
        android:layout_alignRight="@+id/textView13"
        android:layout_alignEnd="@+id/textView13" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="External/WIFI IP = "
        android:id="@+id/textView6"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:layout_below="@+id/textView11"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="..."
        android:id="@+id/textView7"
        android:layout_alignTop="@+id/textView6"
        android:layout_alignRight="@+id/textView14"
        android:layout_alignEnd="@+id/textView14" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Accuracy (meter) = "
        android:id="@+id/textView8"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:layout_below="@+id/textView4"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="..."
        android:id="@+id/textView15"
        android:layout_alignTop="@+id/textView8"
        android:layout_alignLeft="@+id/textView12"
        android:layout_alignStart="@+id/textView12" />


</RelativeLayout>

为了更好地理解我在应用程序中真正想要的内容,以下是一个解释:

我希望我的MainActivity能够在Android设备启动时运行,这样每次我启动手机时它都会在后台向Google表单发送位置数据。


你在清单文件中指定了启动活动吗?请提供您的清单文件内容。 - coolguy
不理解你的问题。所以你是说当你按下 button2 时它可以工作?那么 button2onClick() 方法是什么?如果你想在你的活动开始时执行点击后的操作,你只需要在 MainActivityonCreate() 方法中做同样的事情(当然,你应该将这些操作移动到某个方法中以避免重复代码)。 - coolguy
所以我说,你能做些什么来实现它呢 :) - coolguy
你可以举个例子吗?因为我不太清楚怎么做… =S - user5609622
我没有onClick事件。你看,我在MainActivity中有“Button button2 = (Button)findViewById(R.id.button2);”。抱歉有点含糊,我是Android Studio/Java的新手。 - user5609622
显示剩余4条评论
1个回答

0

启动接收器没有问题,它可以正确地启动您的服务。

问题出在您的服务上,除了显示一个toast之外,它什么也不做。实际的数据发送工作是由MainActivity完成的,每当位置发生变化时,无论您是否点击button2来启动服务,它都会继续进行,即使您点击按钮停止服务,它也会继续进行,因为服务什么也不做。

您需要做的是将发送数据的代码部分从MainActivity移动到服务中。

此外,像这样的应用程序会非常消耗电池。我建议减少数据传输的频率,只获取对您真正重要的内容。

可以尝试类似以下的方式:

public class MyService extends Service {

    private AlarmManager alarmMgr;
    private PendingIntent alarmIntent;
    private double longitude;
    private double latitude;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        //Here you get lat and long
        try {
            LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener);
            Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            longitude = location.getLongitude();
            latitude = location.getLatitude();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


        //You have your latitude and longitude data
        //They are stored in the respective variables
        //Start an AsyncTask to send them wherever you want
        //You could adapt the one in your MainActivity here
        //Or create a different and separate class


        //Here you set an alarm to start the service again in ~15 minutes
        int minutesApart = 15;
        Intent repeat = new Intent(MyService.this, MyService.class);
        alarmIntent = PendingIntent.getService(MyService.this, 0, repeat, 0);
        alarmMgr = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
        alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + minutesApart * 1000, alarmIntent);    

        return START_STICKY;
    }


    private final LocationListener locationListener = new LocationListener() {
        public void onLocationChanged(Location location) {
            longitude = location.getLongitude();
            latitude = location.getLatitude();
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };


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

    @Override
    public void onDestroy() {
        if (alarmMgr!= null) {
            alarmMgr.cancel(alarmIntent);
        }
        super.onDestroy();
    }
}

你需要做的唯一一件事就是创建AsyncTask方法来发送纬度和经度。

附:此服务只能在内存不足时(当释放一些内存时,它将重新启动)或通过从MainActivity按下“按钮”停止。


但是你在主活动(MainActivity)中适应AsyncTask是什么意思?需要适应什么? - user5609622
@Y.Terz:稍微清理一下并进行一些测试以确保它能正常工作,当然我无法做到这一点。 即在您的活动中获取纬度/经度,将它们设置为文本视图中的文本,然后从那里获取文本以便在AsyncTask中传递它们。在这里,您应该简单地传递strLat/strLon值。对于strMod、strMan、strId和strAcc(您必须在服务中创建它们),也是如此。 - Ruocco
是的,你可以复制你的AsyncTask,但你必须先在服务中创建要传递给它的字符串,否则会出现ArrayOutOfBoundException。 试着理解你自己的代码,当你看到: postDataTask.execute(URL, textView3.getText().toString(), ...); 你正在将你的textview的值作为字符串传递给AsyncTask。在服务中不能这样做,否则你会得到NPE,因此你必须创建相同的字符串(就像在MainActivity中一样),并将它们传递给AsyncTask,而不是首先将它们设置为textview的文本。 这是剪切粘贴,但你必须知道什么。 - Ruocco
使用日志来确定 BroadcastReceiver 或 Service 的问题,其中一个可能没有正确启动。另外,尝试在清单文件中的接收器声明中添加 android:enabled="true"(位于 android:name=".BootReceiver" 直下) 。 - Ruocco
奇怪的是,在启动时它会启动应用程序并运行MyService,但仍然无法发送数据。 - user5609622
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接