安卓系统6.0安装程序闪退,控制台下没有报错信息、

来源:互联网 发布:win10 禁用windows 键 编辑:程序博客网 时间:2024/04/30 13:35

写了一个小demo,总经理要我发送APK给他,发送过去之后出现闪退问题。

E/HAL: load: id=gralloc != hmi->id=gralloc
I/HwCust: Constructor found for class android.app.HwCustHwWallpaperManagerImpl
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable


解决方案:

解决方案1:
targSdk 看是不是 没有6.0

解决方案2:
minSdkVersion 一般设置最小的就行 最大的不设


解决方案3:
你是用的方法可能是不是6.0中被改了或者根本就没有废弃掉了

解决方案4:

在java代码中进行动态添加权限;


PermissionsManager代码如下:

/**
 * Copyright 2015 Anthony Restaino

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 either express or implied. See the License for the specific language governing
 permissions and limitations under the License.
 */
package com.cljz.makepassenger.runtimepermissions;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * A class to help you manage your permissions simply.
 */
public class PermissionsManager {

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

  private final Set<String> mPendingRequests = new HashSet<String>(1);
  private final Set<String> mPermissions = new HashSet<String>(1);
  private final List<WeakReference<PermissionsResultAction>> mPendingActions = new ArrayList<WeakReference<PermissionsResultAction>>(1);

  private static PermissionsManager mInstance = null;

  public static PermissionsManager getInstance() {
    if (mInstance == null) {
      mInstance = new PermissionsManager();
    }
    return mInstance;
  }

  private PermissionsManager() {
    initializePermissionsMap();
  }

  /**
   * This method uses reflection to read all the permissions in the Manifest class.
   * This is necessary because some permissions do not exist on older versions of Android,
   * since they do not exist, they will be denied when you check whether you have permission
   * which is problematic since a new permission is often added where there was no previous
   * permission required. We initialize a Set of available permissions and check the set
   * when checking if we have permission since we want to know when we are denied a permission
   * because it doesn't exist yet.
   */
  private synchronized void initializePermissionsMap() {
    Field[] fields = Manifest.permission.class.getFields();
    for (Field field : fields) {
      String name = null;
      try {
        name = (String) field.get("");
      } catch (IllegalAccessException e) {
        Log.e(TAG, "Could not access field", e);
      }
      mPermissions.add(name);
    }
  }

  /**
   * This method retrieves all the permissions declared in the application's manifest.
   * It returns a non null array of permisions that can be declared.
   *
   * @param activity the Activity necessary to check what permissions we have.
   * @return a non null array of permissions that are declared in the application manifest.
   */
  @NonNull
  private synchronized String[] getManifestPermissions(@NonNull final Activity activity) {
    PackageInfo packageInfo = null;
    List<String> list = new ArrayList<String>(1);
    try {
      Log.d(TAG, activity.getPackageName());
      packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
    } catch (PackageManager.NameNotFoundException e) {
      Log.e(TAG, "A problem occurred when retrieving permissions", e);
    }
    if (packageInfo != null) {
      String[] permissions = packageInfo.requestedPermissions;
      if (permissions != null) {
        for (String perm : permissions) {
          Log.d(TAG, "Manifest contained permission: " + perm);
          list.add(perm);
        }
      }
    }
    return list.toArray(new String[list.size()]);
  }

  /**
   * This method adds the {@link PermissionsResultAction} to the current list
   * of pending actions that will be completed when the permissions are
   * received. The list of permissions passed to this method are registered
   * in the PermissionsResultAction object so that it will be notified of changes
   * made to these permissions.
   *
   * @param permissions the required permissions for the action to be executed.
   * @param action      the action to add to the current list of pending actions.
   */
  private synchronized void addPendingAction(@NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    if (action == null) {
      return;
    }
    action.registerPermissions(permissions);
    mPendingActions.add(new WeakReference<PermissionsResultAction>(action));
  }

  /**
   * This method removes a pending action from the list of pending actions.
   * It is used for cases where the permission has already been granted, so
   * you immediately wish to remove the pending action from the queue and
   * execute the action.
   *
   * @param action the action to remove
   */
  private synchronized void removePendingAction(@Nullable PermissionsResultAction action) {
    for (Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
        iterator.hasNext(); ) {
      WeakReference<PermissionsResultAction> weakRef = iterator.next();
      if (weakRef.get() == action || weakRef.get() == null) {
        iterator.remove();
      }
    }
  }

  /**
   * This static method can be used to check whether or not you have a specific permission.
   * It is basically a less verbose method of using {@link ActivityCompat#checkSelfPermission(Context, String)}
   * and will simply return a boolean whether or not you have the permission. If you pass
   * in a null Context object, it will return false as otherwise it cannot check the permission.
   * However, the Activity parameter is nullable so that you can pass in a reference that you
   * are not always sure will be valid or not (e.g. getActivity() from Fragment).
   *
   * @param context    the Context necessary to check the permission
   * @param permission the permission to check
   * @return true if you have been granted the permission, false otherwise
   */
  @SuppressWarnings("unused")
  public synchronized boolean hasPermission(@Nullable Context context, @NonNull String permission) {
    return context != null && (ActivityCompat.checkSelfPermission(context, permission)
        == PackageManager.PERMISSION_GRANTED || !mPermissions.contains(permission));
  }

  /**
   * This static method can be used to check whether or not you have several specific permissions.
   * It is simpler than checking using {@link ActivityCompat#checkSelfPermission(Context, String)}
   * for each permission and will simply return a boolean whether or not you have all the permissions.
   * If you pass in a null Context object, it will return false as otherwise it cannot check the
   * permission. However, the Activity parameter is nullable so that you can pass in a reference
   * that you are not always sure will be valid or not (e.g. getActivity() from Fragment).
   *
   * @param context     the Context necessary to check the permission
   * @param permissions the permissions to check
   * @return true if you have been granted all the permissions, false otherwise
   */
  @SuppressWarnings("unused")
  public synchronized boolean hasAllPermissions(@Nullable Context context, @NonNull String[] permissions) {
    if (context == null) {
      return false;
    }
    boolean hasAllPermissions = true;
    for (String perm : permissions) {
      hasAllPermissions &= hasPermission(context, perm);
    }
    return hasAllPermissions;
  }

  /**
   * This method will request all the permissions declared in your application manifest
   * for the specified {@link PermissionsResultAction}. The purpose of this method is to enable
   * all permissions to be requested at one shot. The PermissionsResultAction is used to notify
   * you of the user allowing or denying each permission. The Activity and PermissionsResultAction
   * parameters are both annotated Nullable, but this method will not work if the Activity
   * is null. It is only annotated Nullable as a courtesy to prevent crashes in the case
   * that you call this from a Fragment where {@link Fragment#getActivity()} could yield
   * null. Additionally, you will not receive any notification of permissions being granted
   * if you provide a null PermissionsResultAction.
   *
   * @param activity the Activity necessary to request and check permissions.
   * @param action   the PermissionsResultAction used to notify you of permissions being accepted.
   */
  @SuppressWarnings("unused")
  public synchronized void requestAllManifestPermissionsIfNecessary(final @Nullable Activity activity,
      final @Nullable PermissionsResultAction action) {
    if (activity == null) {
      return;
    }
    String[] perms = getManifestPermissions(activity);
    requestPermissionsIfNecessaryForResult(activity, perms, action);
  }

  /**
   * This method should be used to execute a {@link PermissionsResultAction} for the array
   * of permissions passed to this method. This method will request the permissions if
   * they need to be requested (i.e. we don't have permission yet) and will add the
   * PermissionsResultAction to the queue to be notified of permissions being granted or
   * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
   * The Activity variable is nullable, but if it is null, the method will fail to execute.
   * This is only nullable as a courtesy for Fragments where getActivity() may yeild null
   * if the Fragment is not currently added to its parent Activity.
   *
   * @param activity    the activity necessary to request the permissions.
   * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
   * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
   */
  @SuppressWarnings("unused")
  public synchronized void requestPermissionsIfNecessaryForResult(@Nullable Activity activity,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    if (activity == null) {
      return;
    }
    addPendingAction(permissions, action);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      doPermissionWorkBeforeAndroidM(activity, permissions, action);
    } else {
      List<String> permList = getPermissionsListToRequest(activity, permissions, action);
      if (permList.isEmpty()) {
        //if there is no permission to request, there is no reason to keep the action int the list
        removePendingAction(action);
      } else {
        String[] permsToRequest = permList.toArray(new String[permList.size()]);
        mPendingRequests.addAll(permList);
        ActivityCompat.requestPermissions(activity, permsToRequest, 1);
      }
    }
  }

  /**
   * This method should be used to execute a {@link PermissionsResultAction} for the array
   * of permissions passed to this method. This method will request the permissions if
   * they need to be requested (i.e. we don't have permission yet) and will add the
   * PermissionsResultAction to the queue to be notified of permissions being granted or
   * denied. In the case of pre-Android Marshmallow, permissions will be granted immediately.
   * The Fragment variable is used, but if {@link Fragment#getActivity()} returns null, this method
   * will fail to work as the activity reference is necessary to check for permissions.
   *
   * @param fragment    the fragment necessary to request the permissions.
   * @param permissions the list of permissions to request for the {@link PermissionsResultAction}.
   * @param action      the PermissionsResultAction to notify when the permissions are granted or denied.
   */
  @SuppressWarnings("unused")
  public synchronized void requestPermissionsIfNecessaryForResult(@NonNull Fragment fragment,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    Activity activity = fragment.getActivity();
    if (activity == null) {
      return;
    }
    addPendingAction(permissions, action);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      doPermissionWorkBeforeAndroidM(activity, permissions, action);
    } else {
      List<String> permList = getPermissionsListToRequest(activity, permissions, action);
      if (permList.isEmpty()) {
        //if there is no permission to request, there is no reason to keep the action int the list
        removePendingAction(action);
      } else {
        String[] permsToRequest = permList.toArray(new String[permList.size()]);
        mPendingRequests.addAll(permList);
        fragment.requestPermissions(permsToRequest, 1);
      }
    }
  }

  /**
   * This method notifies the PermissionsManager that the permissions have change. If you are making
   * the permissions requests using an Activity, then this method should be called from the
   * Activity callback onRequestPermissionsResult() with the variables passed to that method. If
   * you are passing a Fragment to make the permissions request, then you should call this in
   * the {@link Fragment#onRequestPermissionsResult(int, String[], int[])} method.
   * It will notify all the pending PermissionsResultAction objects currently
   * in the queue, and will remove the permissions request from the list of pending requests.
   *
   * @param permissions the permissions that have changed.
   * @param results     the values for each permission.
   */
  @SuppressWarnings("unused")
  public synchronized void notifyPermissionsChange(@NonNull String[] permissions, @NonNull int[] results) {
    int size = permissions.length;
    if (results.length < size) {
      size = results.length;
    }
    Iterator<WeakReference<PermissionsResultAction>> iterator = mPendingActions.iterator();
    while (iterator.hasNext()) {
      PermissionsResultAction action = iterator.next().get();
      for (int n = 0; n < size; n++) {
        if (action == null || action.onResult(permissions[n], results[n])) {
          iterator.remove();
          break;
        }
      }
    }
    for (int n = 0; n < size; n++) {
      mPendingRequests.remove(permissions[n]);
    }
  }

  /**
   * When request permissions on devices before Android M (Android 6.0, API Level 23)
   * Do the granted or denied work directly according to the permission status
   *
   * @param activity    the activity to check permissions
   * @param permissions the permissions names
   * @param action      the callback work object, containing what we what to do after
   *                    permission check
   */
  private void doPermissionWorkBeforeAndroidM(@NonNull Activity activity,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    for (String perm : permissions) {
      if (action != null) {
        if (!mPermissions.contains(perm)) {
          action.onResult(perm, Permissions.NOT_FOUND);
        } else if (ActivityCompat.checkSelfPermission(activity, perm)
            != PackageManager.PERMISSION_GRANTED) {
          action.onResult(perm, Permissions.DENIED);
        } else {
          action.onResult(perm, Permissions.GRANTED);
        }
      }
    }
  }

  /**
   * Filter the permissions list:
   * If a permission is not granted, add it to the result list
   * if a permission is granted, do the granted work, do not add it to the result list
   *
   * @param activity    the activity to check permissions
   * @param permissions all the permissions names
   * @param action      the callback work object, containing what we what to do after
   *                    permission check
   * @return a list of permissions names that are not granted yet
   */
  @NonNull
  private List<String> getPermissionsListToRequest(@NonNull Activity activity,
      @NonNull String[] permissions,
      @Nullable PermissionsResultAction action) {
    List<String> permList = new ArrayList<String>(permissions.length);
    for (String perm : permissions) {
      if (!mPermissions.contains(perm)) {
        if (action != null) {
          action.onResult(perm, Permissions.NOT_FOUND);
        }
      } else if (ActivityCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) {
        if (!mPendingRequests.contains(perm)) {
          permList.add(perm);
        }
      } else {
        if (action != null) {
          action.onResult(perm, Permissions.GRANTED);
        }
      }
    }
    return permList;
  }

}

PermissionsResultAction代码如下:

/**
 * Copyright 2015 Anthony Restaino

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 either express or implied. See the License for the specific language governing
 permissions and limitations under the License.
 */
package com.cljz.makepassenger.runtimepermissions;

import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.util.Log;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * This abstract class should be used to create an if/else action that the PermissionsManager
 * can execute when the permissions you request are granted or denied. Simple use involves
 * creating an anonymous instance of it and passing that instance to the
 * requestPermissionsIfNecessaryForResult method. The result will be sent back to you as
 * either onGranted (all permissions have been granted), or onDenied (a required permission
 * has been denied). Ideally you put your functionality in the onGranted method and notify
 * the user what won't work in the onDenied method.
 */
public abstract class PermissionsResultAction {

  private static final String TAG = PermissionsResultAction.class.getSimpleName();
  private final Set<String> mPermissions = new HashSet<String>(1);
  private Looper mLooper = Looper.getMainLooper();

  /**
   * Default Constructor
   */
  public PermissionsResultAction() {}

  /**
   * Alternate Constructor. Pass the looper you wish the PermissionsResultAction
   * callbacks to be executed on if it is not the current Looper. For instance,
   * if you are making a permissions request from a background thread but wish the
   * callback to be on the UI thread, use this constructor to specify the UI Looper.
   *
   * @param looper the looper that the callbacks will be called using.
   */
  @SuppressWarnings("unused")
  public PermissionsResultAction(@NonNull Looper looper) {mLooper = looper;}

  /**
   * This method is called when ALL permissions that have been
   * requested have been granted by the user. In this method
   * you should put all your permissions sensitive code that can
   * only be executed with the required permissions.
   */
  public abstract void onGranted();

  /**
   * This method is called when a permission has been denied by
   * the user. It provides you with the permission that was denied
   * and will be executed on the Looper you pass to the constructor
   * of this class, or the Looper that this object was created on.
   *
   * @param permission the permission that was denied.
   */
  public abstract void onDenied(String permission);

  /**
   * This method is used to determine if a permission not
   * being present on the current Android platform should
   * affect whether the PermissionsResultAction should continue
   * listening for events. By default, it returns true and will
   * simply ignore the permission that did not exist. Usually this will
   * work fine since most new permissions are introduced to
   * restrict what was previously allowed without permission.
   * If that is not the case for your particular permission you
   * request, override this method and return false to result in the
   * Action being denied.
   *
   * @param permission the permission that doesn't exist on this
   *                   Android version
   * @return return true if the PermissionsResultAction should
   * ignore the lack of the permission and proceed with exection
   * or false if the PermissionsResultAction should treat the
   * absence of the permission on the API level as a denial.
   */
  @SuppressWarnings({"WeakerAccess", "SameReturnValue"})
  public synchronized boolean shouldIgnorePermissionNotFound(String permission) {
    Log.d(TAG, "Permission not found: " + permission);
    return true;
  }

  @SuppressWarnings("WeakerAccess")
  @CallSuper
  protected synchronized final boolean onResult(final @NonNull String permission, int result) {
    if (result == PackageManager.PERMISSION_GRANTED) {
      return onResult(permission, Permissions.GRANTED);
    } else {
      return onResult(permission, Permissions.DENIED);
    }

  }

  /**
   * This method is called when a particular permission has changed.
   * This method will be called for all permissions, so this method determines
   * if the permission affects the state or not and whether it can proceed with
   * calling onGranted or if onDenied should be called.
   *
   * @param permission the permission that changed.
   * @param result     the result for that permission.
   * @return this method returns true if its primary action has been completed
   * and it should be removed from the data structure holding a reference to it.
   */
  @SuppressWarnings("WeakerAccess")
  @CallSuper
  protected synchronized final boolean onResult(final @NonNull String permission, Permissions result) {
    mPermissions.remove(permission);
    if (result == Permissions.GRANTED) {
      if (mPermissions.isEmpty()) {
        new Handler(mLooper).post(new Runnable() {
          @Override
          public void run() {
            onGranted();
          }
        });
        return true;
      }
    } else if (result == Permissions.DENIED) {
      new Handler(mLooper).post(new Runnable() {
        @Override
        public void run() {
          onDenied(permission);
        }
      });
      return true;
    } else if (result == Permissions.NOT_FOUND) {
      if (shouldIgnorePermissionNotFound(permission)) {
        if (mPermissions.isEmpty()) {
          new Handler(mLooper).post(new Runnable() {
            @Override
            public void run() {
              onGranted();
            }
          });
          return true;
        }
      } else {
        new Handler(mLooper).post(new Runnable() {
          @Override
          public void run() {
            onDenied(permission);
          }
        });
        return true;
      }
    }
    return false;
  }

  /**
   * This method registers the PermissionsResultAction object for the specified permissions
   * so that it will know which permissions to look for changes to. The PermissionsResultAction
   * will then know to look out for changes to these permissions.
   *
   * @param perms the permissions to listen for
   */
  @SuppressWarnings("WeakerAccess")
  @CallSuper
  protected synchronized final void registerPermissions(@NonNull String[] perms) {
    Collections.addAll(mPermissions, perms);
  }
}

视图内必要代码




0 0