簡體   English   中英

有人可以告訴我我的Android應用程序有什么問題嗎

[英]Can someone tell me what is wrong with my android app

我寫了一個android應用程序,基本上可以跟蹤GPS坐標的時間和地址。

我有3個清單,每個清單分別對應Lyft,Uber和其他。

但是我相信我的應用開始放慢我的智能手機(三星Galaxy S7 Edge,帶有Android O)

有人可以看一下我的代碼並告訴我為什么它會使我的智能手機變慢。

我的假設是,可能是線程同步問題。

附上我的代碼

1)MainActivity.java

package com.milind.myapp.gpstrackingservice;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.PowerManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.ActionMode;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements AddressListener
{
    private static final String TAG = MainActivity.class.getSimpleName();
    private PowerManager.WakeLock wakeLock;
    private TextView labelAddress;
    private TextView multiTextLyft;
    private TextView multiTextUber;
    private TextView multiTextOther;

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

        labelAddress = findViewById(R.id.label_address);
        multiTextLyft = findViewById(R.id.multi_text_lyft);
        multiTextUber = findViewById(R.id.multi_text_uber);
        multiTextOther = findViewById(R.id.multi_text_other);
        if (MyService.isServiceStarted())
        {
            MyService.getInstance().load(getSharedPrefs());
            refreshAllViews();
        }

        PowerManager powerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "myapp:My Lock");
    }

    @Override
    protected void onStart()
    {
        super.onStart();
        ActivityCompat.requestPermissions(this, new String[]
                {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WAKE_LOCK}, 1);

        if (!MyService.isServiceStarted())
        {
            Intent intent = new Intent(this, MyService.class);
            intent.setAction(MyService.ACTION_START_SERVICE);

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            {
                startForegroundService(intent);
            }
            else
            {
                startService(intent);
            }
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus)
    {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus)
        {
            if (MyService.isServiceStarted())
            {
                MyService.getInstance().registerAddressListener(this);
            }
            wakeLock.acquire();
        }
        else
        {
            if (MyService.isServiceStarted())
            {
                MyService.getInstance().unregisterAddressListener(this);
            }
            wakeLock.release();
        }
    }


    public void onRequestPermissionsResult(int requestCode, String permissions[],
                                           int[] grantResults)
    {
        switch (requestCode)
        {
            case 1:
            {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                {

                }
                else
                {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            }
            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

    @Override
    public void onLocationChanged(Location loc)
    {
        final String address = MyService.getAddress(this, loc);
        final CharSequence text = labelAddress.getText();
        if (text.toString().equals(address))
        {
            return;
        }

        MyService.getInstance().load(getSharedPrefs());
        labelAddress.setText(address);

        refreshAllViews();

        new Tone().play(880);
    }

    private void refreshAllViews()
    {
        runOnUiThread(new Runnable()
        {
            public void run()
            {
                refereshEditTextLyft();
                refereshEditTextUber();
                refereshEditTextOther();
            }
        });
    }

    private void refereshEditTextLyft()
    {
        multiTextLyft.setText(MyService.getInstance().getLyftAddresses());
    }

    private void refereshEditTextUber()
    {
        multiTextUber.setText(MyService.getInstance().getUberAddresses());
    }

    private void refereshEditTextOther()
    {
        multiTextOther.setText(MyService.getInstance().getOtherAddresses());
    }

    private SharedPreferences getSharedPrefs()
    {
        return getSharedPreferences("name", MODE_PRIVATE);
    }

    public void onLyftButtonClicked(View view)
    {
        MyService.getInstance().addLyftAddress(labelAddress.getText());
        new Tone().play(440);
        refereshEditTextLyft();

        MyService.getInstance().save(getSharedPrefs());
    }

    public void onUberButtonClicked(View view)
    {
        MyService.getInstance().addUberAddress(labelAddress.getText());
        new Tone().play(440);
        refereshEditTextUber();

        MyService.getInstance().save(getSharedPrefs());
    }

    public void onOtherButtonClicked(View view)
    {
        MyService.getInstance().addOtherAddress(labelAddress.getText());
        new Tone().play(440);
        refereshEditTextOther();

        MyService.getInstance().save(getSharedPrefs());
    }

    public void onClearButtonClicked(View view)
    {
        if (MyService.isServiceStarted())
        {
            SharedPreferences sharedPreferences = getSharedPrefs();
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.clear();
            editor.commit();
            MyService.getInstance().clear();
            refereshEditTextLyft();
            refereshEditTextUber();
            refereshEditTextOther();
        }
    }

    public void onDelLyftButtonClicked(View view)
    {
        MyService.getInstance().delLyftEntry();
        new Tone().play(440);
        refereshEditTextLyft();

        MyService.getInstance().save(getSharedPrefs());
    }

    public void onDelUberButtonClicked(View view)
    {
        MyService.getInstance().delUberEntry();
        new Tone().play(440);
        refereshEditTextUber();

        MyService.getInstance().save(getSharedPrefs());
    }

    public void onDelOtherButtonClicked(View view)
    {
        MyService.getInstance().delOtherEntry();
        new Tone().play(440);
        refereshEditTextOther();

        MyService.getInstance().save(getSharedPrefs());
    }

    @Override
    protected void onRestart()
    {
        super.onRestart();
    }

    @Override
    public void onActionModeFinished(ActionMode mode)
    {
        super.onActionModeFinished(mode);
    }

    @Override
    public void onBackPressed()
    {
        super.onBackPressed();
    }
}

2)MyService.java

package com.milind.myapp.gpstrackingservice;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class MyService extends Service implements LocationListener
{
    private static final String TAG = MyService.class.getSimpleName();
    public static final String ACTION_START_SERVICE = "ACTION_START_SERVICE";
    public static final String ACTION_STOP_SERVICE = "ACTION_STOP_SERVICE";
    public static final String ACTION_UBER = "ACTION_UBER";
    public static final String ACTION_LYFT = "ACTION_UBER";
    public static final String ACTION_END = "ACTION_END";
    public static final String LYFT_PREFIX = "Lyft";
    public static final String OTHER_PREFIX = "Other";
    public static final String UBER_PREFIX = "Uber";

    private static MyService mInstance = null;

    private List<AddressListener> listeners = new ArrayList<>();
    private List<AddressPoint> lyftAddresses = new ArrayList<>();
    private List<AddressPoint> uberAddresses = new ArrayList<>();
    private List<AddressPoint> otherAddresses = new ArrayList<>();
    private Location mLastLocation;

    public MyService()
    {
        super();
        Log.d(TAG, "MyService(): constructor called");
    }

    public static boolean isServiceStarted()
    {
        Log.d(TAG, "isServiceStarted()");
        return mInstance != null;
    }

    public static final MyService getInstance()
    {
        return mInstance;
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        Log.d(TAG, "onBind(Intent intent)");
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.d(TAG, "onStartCommand(Intent, flags, startId) : " + hashCode());
        Log.d(TAG, "onStartCommand(...) intent=" + intent + "=" + ", flags=" + flags + ", startId=" + startId);
        Log.d(TAG, "onStartCommand(...) isServiceStarted=" + isServiceStarted());
        String action = null;
        if (intent != null)
        {
            Log.d(TAG, intent.toString());
            action = intent.getAction();
        }
        else
        {
            Log.d(TAG, "onStartCommand(...): early return");
            return super.onStartCommand(intent, flags, startId);
        }

        if (isServiceStarted() == false && action == ACTION_START_SERVICE)
        {
            Log.d(TAG, "onStartCommand(...): Service starting=" + startId);
            //startForegroundServivceNotification()
            startRunningInForeground();
            requestLocationUpdates();
            mInstance = this;
            Log.d(TAG, "onStartCommand(...): Service started=" + startId);
        }
        else if (isServiceStarted() == true && action == ACTION_STOP_SERVICE)
        {
            Log.d(TAG, "onStartCommand(...): Service stopping=" + startId);
            stopLocationUpdates();
            stopSelf();
            Log.d(TAG, "onStartCommand(...): Service stop requested" + startId);
            mInstance = null;
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy()
    {
        Log.d(TAG, "onDestroy(): Service destroyed");
        super.onDestroy();
        mInstance = null;
    }

    private void stopLocationUpdates()
    {
        Log.d(TAG, "stopLocationUpdates()");
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locationManager.removeUpdates(this);
    }

    private void requestLocationUpdates()
    {
        Log.d(TAG, "requestLocationUpdates()");
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        try
        {
            locationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, 1500, 0, this);
            Log.w(TAG, "requestLocationUpdates(): ended gracefully");
        }
        catch (SecurityException ex)
        {
            Log.w(TAG, "requestLocationUpdates(): Exception");
            ex.printStackTrace();
        }
    }

    @Override
    public void onLocationChanged(Location location)
    {
        Log.v(TAG, "onLocationChanged(Location location): started, location=" + location.toString());
        dispatchLocationChange(location);
        mLastLocation = location;
        Log.v(TAG, "onLocationChanged: completed");
    }

    private void dispatchLocationChange(Location loc)
    {
        Log.v(TAG, "dispatchLocationChange(Location)");
        for (AddressListener listener : listeners)
        {
            listener.onLocationChanged(loc);
        }
    }

    public static String getAddress(Context context, Location loc)
    {
        Log.v(TAG, "getAddress(Location loc) started");
        List<Address> addresses;
        Geocoder gcd = new Geocoder(context, Locale.getDefault());
        try
        {
            addresses = gcd.getFromLocation(loc.getLatitude(),
                    loc.getLongitude(), 1);
            String strReturnAddress = "";

            if (addresses != null && addresses.size() > 0)
            {
                final Address address = addresses.get(0);
                Log.d(TAG, address.toString());
                String addressLines = "";

                Log.v(TAG, "Locale: " + address.getLocale());

                for (int i = 0; i <= address.getMaxAddressLineIndex(); ++i)
                {
                    Log.v(TAG, "AddressLine " + i + ": " + address.getAddressLine(i));
                    addressLines += address.getAddressLine(i) + ", ";
                    Log.v(TAG, "addressLines:" + addressLines);
                }

                String strAddress =
                        addressLines
                        ;
                Log.v(TAG, "strAddress:" + strAddress);

                strReturnAddress = strAddress.substring(0, strAddress.length() - 2);
                Log.v(TAG, "strReturnAddress:" + strReturnAddress);
            }
            Log.d(TAG, "getAddress(Location loc) completed with return=" + strReturnAddress);
            return strReturnAddress;
        }
        catch (IOException e)
        {
            e.printStackTrace();
            Log.d(TAG, "Exception", e);
        }

        Log.d(TAG, "getAddress(Location loc) completed with return=null");
        return "";
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    {
        Log.d(TAG, "onStatusChanged(provider, status, extras): status=" + status + ", extras=" + extras);

    }

    @Override
    public void onProviderEnabled(String provider)
    {
        Log.d(TAG, "onProviderEnabled(provider) ");
    }

    @Override
    public void onProviderDisabled(String provider)
    {
        Log.d(TAG, "onProviderDisabled(provider) ");
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    private static void logGetProperties(final String tag, final Object obj)
    {
        Log.v(tag, "logGetProperties(...)");
        Class cls = obj.getClass();

        Method[] methods = cls.getMethods();
        Log.v(tag, "methods.length = " + methods.length);

        for (Method method : methods)
        {
            String methodName = method.getName();
            Log.v(tag, "methodName = " + methodName);

            if (methodName.startsWith("get")
                    && (method.getParameters() == null || method.getParameters().length == 0)
                    && method.getReturnType() != Void.class)
            {
                try
                {
                    Log.v(tag, methodName + " = " + method.invoke(obj, new Object[0]));
                }
                catch (Exception ex)
                {
                    Log.e(tag, methodName + " Failed (exception)");
                }
            }
        }
    }

    public AddressListener registerAddressListener(AddressListener listener)
    {
        Log.d(TAG, "registerAddressListener(AddressListener)");
        if (!listeners.contains(listener))
        {
            listeners.add(listener);
        }
        return listener;
    }

    public AddressListener unregisterAddressListener(AddressListener listener)
    {
        Log.d(TAG, "unregisterAddressListener(AddressListener)");
        if (listeners.contains(listener))
        {
            listeners.remove(listener);
            Log.d(TAG, "unregisterAddressListener(AddressListener): Listener removed");
            return listener;
        }
        Log.d(TAG, "unregisterAddressListener(AddressListener): Listener not found");
        return null;
    }

    public void addLyftAddress(CharSequence text)
    {
        Log.d(TAG, "addLyftAddress(CharSequence text): text: " + text);
        lyftAddresses.add(new AddressPoint(System.currentTimeMillis(), text));
    }

    public void addUberAddress(CharSequence text)
    {
        Log.d(TAG, "addUberAddress(CharSequence text): text: " + text);
        uberAddresses.add(new AddressPoint(System.currentTimeMillis(), text));
    }

    public void addOtherAddress(CharSequence text)
    {
        Log.d(TAG, "addOtherAddress(CharSequence text): text: " + text);
        otherAddresses.add(new AddressPoint(System.currentTimeMillis(), text));
    }

    String getLyftAddresses()
    {
        return getAddresses(lyftAddresses);
    }

    String getUberAddresses()
    {
        return getAddresses(uberAddresses);
    }

    String getOtherAddresses()
    {
        return getAddresses(otherAddresses);
    }

    private String getAddresses(List<AddressPoint> addresses)
    {
        Log.d(TAG, "getAddresses(List<AddressPoint>)");
        String strAddresses = "" + addresses.size() + "\n--------\n";
        for (int i = 0; i < addresses.size(); ++i)
        {
            AddressPoint addresspoint = addresses.get(i);
            strAddresses += addresspoint + "\n--------\n";

            if ((i % 2) != 0)
            {
                strAddresses += "\n\n";
            }
        }
        return strAddresses;
    }

    private void startRunningInForeground()
    {
        //if more than or equal to 26
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
        {
            //if more than 26
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O)
            {
                String CHANNEL_ONE_ID = "Package.Service";
                String CHANNEL_ONE_NAME = "Screen service";
                NotificationChannel notificationChannel = null;
                notificationChannel = new NotificationChannel(CHANNEL_ONE_ID,
                        CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_MIN);
                notificationChannel.enableLights(true);
                notificationChannel.setLightColor(Color.RED);
                notificationChannel.setShowBadge(true);
                notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
                NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                if (manager != null)
                {
                    manager.createNotificationChannel(notificationChannel);
                }

                Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);
                Notification notification = new Notification.Builder(getApplicationContext())
                        .setChannelId(CHANNEL_ONE_ID)
                        .setContentTitle("Recording data")
                        .setContentText("App is running background operations")
                        .setSmallIcon(R.drawable.ic_launcher_background)
                        .setLargeIcon(icon)
                        .build();

                Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
                notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                notification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);

                startForeground(101, notification);
            }
            //if version 26
            else
            {
                startForeground(101, updateNotification());
            }
        }
        //if less than version 26
        else
        {
            Notification notification = new NotificationCompat.Builder(this)
                    .setContentTitle("App")
                    .setContentText("App is running background operations")
                    .setSmallIcon(R.drawable.ic_launcher_foreground)
                    .setOngoing(true).build();

            startForeground(101, notification);
        }
    }

    private Notification updateNotification()
    {

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        return new NotificationCompat.Builder(this)
                .setContentTitle("Activity log")
                .setTicker("Ticker")
                .setContentText("app is running background operations")
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentIntent(pendingIntent)
                .setOngoing(true).build();
    }

    public void load(final SharedPreferences lSharedPrefs)
    {
        Log.w(TAG, "load(SharedPreferences): started");
        load(lSharedPrefs, lyftAddresses, LYFT_PREFIX);
        load(lSharedPrefs, uberAddresses, UBER_PREFIX);
        load(lSharedPrefs, otherAddresses, OTHER_PREFIX);
        Log.w(TAG, "load(SharedPreferences): completed");
    }

    private void load(final SharedPreferences lSharedPrefs, final List<AddressPoint> lAddrPoints, final String lPrefix)
    {
        Log.w(TAG, "load(SharedPreferences, lAddrPoints, lPrefix)");
        lAddrPoints.clear();
        final int count = lSharedPrefs.getInt(lPrefix + "Count", lAddrPoints.size());
        for (int i = 0; i < count; ++i)
        {
            String address = lSharedPrefs.getString(lPrefix + "Address" + i, null);
            final long time = lSharedPrefs.getLong(lPrefix + "Time" + i, 0);

            //if address or time is invalid skip to the next entry
            if (address == null || time == 0)
            {
                continue;
            }

            final AddressPoint addressPoint = new AddressPoint(time, address);
            lAddrPoints.add(addressPoint);
        }
    }

    private void save(final SharedPreferences lSharedPrefs, final List<AddressPoint> lAddrPoints, final String lPrefix)
    {
        Log.w(TAG, "save(SharedPreferences, lAddrPoints, lPrefix)");
        SharedPreferences.Editor editor = lSharedPrefs.edit();
        final int count = lAddrPoints.size();

        //Save the count
        editor.putInt(lPrefix + "Count", count);
        for (int i = 0; i < count; ++i)
        {
            //Save the entry
            AddressPoint lAddrPoint = lAddrPoints.get(i);
            editor.putLong(lPrefix + "Time" + i, lAddrPoint.getTime());
            editor.putString(lPrefix + "Address" + i, (String) lAddrPoint.getAddress());
        }
        Log.w(TAG, "save(sharedFrefs, List, String): commit");
        editor.commit();
    }

    public void save(final SharedPreferences sharedPreferences)
    {
        Log.w(TAG, "save(SharedPreferences): started");
        Log.w(TAG, "save: lyftAddresses");
        save(sharedPreferences, lyftAddresses, LYFT_PREFIX);

        Log.w(TAG, "save: uberAddresses");
        save(sharedPreferences, uberAddresses, UBER_PREFIX);

        Log.w(TAG, "save: otherAddresses");
        save(sharedPreferences, otherAddresses, OTHER_PREFIX);
        Log.w(TAG, "save(SharedPreferences) completed");
    }

    public void clear()
    {
        lyftAddresses.clear();
        uberAddresses.clear();
        otherAddresses.clear();
    }

    public void delLyftEntry()
    {
        if (lyftAddresses.size() > 0)
        {
            lyftAddresses.remove(lyftAddresses.size() - 1);
        }
    }

    public void delUberEntry()
    {
        if (uberAddresses.size() > 0)
        {
            uberAddresses.remove(uberAddresses.size() - 1);
        }
    }

    public void delOtherEntry()
    {
        if (otherAddresses.size() > 0)
        {
            otherAddresses.remove(otherAddresses.size() - 1);
        }
    }
}

3) activity_main.xml

4) AndroidManifest.xml

用這個詞的正常含義來說,這(可能)不是線程問題。 發生的事情是您在主線程上執行了GeoCoder.getFromLocation()調用。 根據文檔

可以通過網絡查找獲得返回的值。 ...從與主UI線程分開的線程中調用此方法可能很有用。

這意味着該方法每次被調用可能會阻塞幾秒鍾。 如果您要開車穿越雜亂無章的小區,則更有可能。 由於該方法是在每次位置更新時(大約每2秒)調用一次,因此UI處於掛起狀態是可以理解的。

建議的修復

將您的getAddress()函數替換為AsyncTask ,該函數將getFromLocation()調用移至后台線程( 現在,您的應用程序將真正成為多線程)。 這樣的事情應該起作用:

private class GetFromLocationTask extends AsyncTask<Location, Void, List<Address>> {
    protected List<Address> doInBackground(Location... locs) {
        return gcd.getFromLocation(locs[ 0 ].getLatitude(), locs[ 0 ].getLongitude(), 1);
    }

    protected void onProgressUpdate(Void... progress) {}

    protected void onPostExecute(List<Address> result) {
        //execute the remainder of your getAddress() logic here 
    }
}

然后,使用new GetFromLocationTask().execute(location)執行它。 調用它而不是getAddress() 您不需要將Context傳遞給getAddress() ,因為Service.this也可以正常工作(它是Context )。

獎金提示:注意onLocationChanged()在UI線程上運行,也是如此refreshAllViews() 這意味着您對runOnUiThread()調用是多余的,它將僅同步執行給定的Runnable

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM