Giter VIP home page Giter VIP logo

androidbox's Issues

Component class com.huawei.hms.support.api.push.PushEventReceiver does not exist in com.xtc.watch

07-25 09:51:01.897 25436-25436/com.xtc.watch E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xtc.watch, PID: 25436
java.lang.RuntimeException: Unable to create application com.xtc.watch.XtcApplication: java.lang.IllegalArgumentException: Component class com.huawei.hms.support.api.push.PushEventReceiver does not exist in com.xtc.watch
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4701)
at android.app.ActivityThread.access$1600(ActivityThread.java:167)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1435)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5401)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:919)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:714)
Caused by: java.lang.IllegalArgumentException: Component class com.huawei.hms.support.api.push.PushEventReceiver does not exist in com.xtc.watch
at android.os.Parcel.readException(Parcel.java:1550)
at android.os.Parcel.readException(Parcel.java:1499)
at android.content.pm.IPackageManager$Stub$Proxy.setComponentEnabledSetting(IPackageManager.java:3394)
at android.app.ApplicationPackageManager.setComponentEnabledSetting(ApplicationPackageManager.java:1492)
at com.xtc.im.phone.thirdpush.a.d(ThirdPushManager.java:242)
at com.xtc.im.phone.thirdpush.a.b(ThirdPushManager.java:132)
at com.xtc.im.phone.IMPhone.startThirdPush(IMPhone.java:154)
at com.xtc.watch.XtcApplication.onCreate(XtcApplication.java:142)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1018)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4698)
at android.app.ActivityThread.access$1600(ActivityThread.java:167) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1435) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5401) 
at java.lang.reflect.Method.invoke(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:372) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:919) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:714)

Neither user 10421 nor current process has android.permission.ACCESS_COARSE_LOCATION.

 Process: com.xxx.xxx.xxx:push, PID: 5783
 java.lang.SecurityException: Neither user 10421 nor current process has android.permission.ACCESS_COARSE_LOCATION.
     at android.os.Parcel.readException(Parcel.java:1546)
     at android.os.Parcel.readException(Parcel.java:1499)
     at com.android.internal.telephony.ITelephony$Stub$Proxy.getAllCellInfoUsingSubId(ITelephony.java:2923)
     at android.telephony.TelephonyManager.getAllCellInfo(TelephonyManager.java:2729)
     at android.telephony.TelephonyManager.getAllCellInfo(TelephonyManager.java:2723)
     at com.xxx.im.core.common.utils.SIMUtil.getMobileDbm(Unknown Source)
     at com.xxx.im.core.common.utils.SIMUtil.isSignalStrong(Unknown Source)
/**
     * 获取手机信号强度,需添加权限 android.permission.ACCESS_COARSE_LOCATION <br>
     * API要求不低于17 <br>
     *
     * @return 当前手机主卡信号强度, 单位 dBm(-1是默认值,表示获取失败)
     */
    private static int getMobileDbm(Context context) {

        int dbm = -1;
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        List<CellInfo> cellInfoList;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            cellInfoList = tm.getAllCellInfo();
            if (null != cellInfoList) {
                for (CellInfo cellInfo : cellInfoList) {
                    if (cellInfo instanceof CellInfoGsm) {//移动
                        CellSignalStrengthGsm cellSignalStrengthGsm = ((CellInfoGsm) cellInfo).getCellSignalStrength();
                        dbm = cellSignalStrengthGsm.getDbm();
                    } else if (cellInfo instanceof CellInfoCdma) {//电信
                        CellSignalStrengthCdma cellSignalStrengthCdma = ((CellInfoCdma) cellInfo).getCellSignalStrength();
                        dbm = cellSignalStrengthCdma.getDbm();
                    } else if (cellInfo instanceof CellInfoWcdma) {//联通
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                            CellSignalStrengthWcdma cellSignalStrengthWcdma = ((CellInfoWcdma) cellInfo).getCellSignalStrength();
                            dbm = cellSignalStrengthWcdma.getDbm();
                        }
                    } else if (cellInfo instanceof CellInfoLte) {//移动
                        CellSignalStrengthLte cellSignalStrengthLte = ((CellInfoLte) cellInfo).getCellSignalStrength();
                        dbm = cellSignalStrengthLte.getDbm();
                    }
                }
            }
        }
        LogUtil.d(TAG,"mobile dbm: "+dbm);
        return dbm;
    }

增加了权限,还是报权限问题。为什么???

SQLite查询操作源码分析:从 IllegalArgumentException:the bind value at index 2 is null 说起

一、问题现象以及结论

1、问题现象

做数据库查询操作时,报了异常 IllegalArgumentException:the bind value at index 2 is null。

2、异常代码片段

cursor = db.query("table_account", null,“account_name” + "=? and "+"account_tel"+ "=? and "+"account_sex"+"=?",new String[]{entity.getName(),entity.getTel(),String.valueOf(entity.getSex())}, null, null, null);

3、问题原因

传入的entity.getTel() 为null了,SQLite内部抛出 IllegalArgumentException ,查询任务终止。

二、详细分析

1、异常出处代码片段

发现直接从db.query方法往下追有点麻烦,分支比较多,所以直接找到异常出处的代码,然后倒追回来。如果不习惯,也可以从后往前看。
IllegalArgumentException("the bind value at index " + index + " is null")。

SQLiteProgram.java[1.1]

    /**
     * Bind a String value to this statement. The value remains bound until
     * {@link #clearBindings} is called.
     *
     * @param index The 1-based index to the parameter to bind
     * @param value The value to bind, must not be null
     */
    public void bindString(int index, String value) {
        if (value == null) {
            throw new IllegalArgumentException("the bind value at index " + index + " is null");
        }
        bind(index, value);
    }

2、代码追踪

### SQLiteProgram.java[1.2]

    /**
     * Given an array of String bindArgs, this method binds all of them in one single call.
     *
     * @param bindArgs the String array of bind args, none of which must be null.
     */
    public void bindAllArgsAsStrings(String[] bindArgs) {
        if (bindArgs != null) {
            for (int i = bindArgs.length; i != 0; i--) {
			bindString(i, bindArgs[i - 1]);//调用[1.1]
            }
        }
    }

SQLiteDirectCursorDriver.java[2.1]

public Cursor query(CursorFactory factory, String[] selectionArgs) {
        final SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, mCancellationSignal);
        final Cursor cursor;
        try {
            query.bindAllArgsAsStrings(selectionArgs);//调用[1.2]

            if (factory == null) {
                cursor = new SQLiteCursor(this, mEditTable, query);// 这里应该是用了 default factory 
            } else {
                cursor = factory.newCursor(mDatabase, this, mEditTable, query);
            }
        } catch (RuntimeException ex) {
            query.close();
            throw ex;
        }

        mQuery = query;
        return cursor;
    }

SQLiteDatabase.java[3.1]

    /**
     * Runs the provided SQL and returns a cursor over the result set.
     *
     * @param cursorFactory the cursor factory to use, or null for the default factory
     */
    public Cursor rawQueryWithFactory(
            CursorFactory cursorFactory, String sql, String[] selectionArgs,
            String editTable, CancellationSignal cancellationSignal) {
        acquireReference();
        try {
            SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
                    cancellationSignal);
					//cursorFactory传入为null则用mCursorFactory
            return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
                    selectionArgs);//调用[2.1]
        } finally {
            releaseReference();
        }
    }

SQLiteDatabase.java[3.2]

 /**
     * Query the given URL, returning a {@link Cursor} over the result set.
     *
     * @param cursorFactory the cursor factory to use, or null for the default factory
     * @param distinct true if you want each row to be unique, false otherwise.
     */
    public Cursor queryWithFactory(CursorFactory cursorFactory,
            boolean distinct, String table, String[] columns,
            String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
        acquireReference();
        try {
            String sql = SQLiteQueryBuilder.buildQueryString(
                    distinct, table, columns, selection, groupBy, having, orderBy, limit);//调用[6.1]

            return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
                    findEditTable(table), cancellationSignal);//调用[3.1]
        } finally {
            releaseReference();
        }
    }

SQLiteDatabase.java[3.3]

 /**
     * Query the given URL, returning a {@link Cursor} over the result set.
     *
     * @param distinct true if you want each row to be unique, false otherwise.
     */
    public Cursor query(boolean distinct, String table, String[] columns,
            String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit) {
        return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
                groupBy, having, orderBy, limit, null);//调用[3.2]
    }

SQLiteDatabase.java[3.4]

  /**
     * Query the given table, returning a {@link Cursor} over the result set.
     *
     * @return A {@link Cursor} object, which is positioned before the first entry. Note that
     * {@link Cursor}s are not synchronized, see the documentation for more details.
     * @see Cursor
     */
    public Cursor query(String table, String[] columns, String selection,
            String[] selectionArgs, String groupBy, String having,
            String orderBy) {

        return query(false, table, columns, selection, selectionArgs, groupBy,
                having, orderBy, null /* limit */);//调用[3.3]
    }

三、扩展问题

1、distinct 这个布尔参数在控制什么

看到上述代码块中的[3.4]调用[3.3]中直接给 distinct 传了false,看代码注释:distinct true if you want each row to be unique, false otherwise.大致意思是我true的时候有一个唯一性的要求。搜索代码如下:

BordeauxSessionStorage[4.1]

    BordeauxSessionManager.Session getSession(String key) {
		//调用[3.3]
        Cursor cursor = mDbSessions.query(true, SESSION_TABLE,
                new String[]{COLUMN_KEY, COLUMN_CLASS, COLUMN_MODEL, COLUMN_TIME},
                COLUMN_KEY + "=\"" + key + "\"", null, null, null, null, null);
        if ((cursor == null) | (cursor.getCount() == 0)) {
            cursor.close();
            return null;
        }
        if (cursor.getCount() > 1) {
            cursor.close();
            throw new RuntimeException("Unexpected duplication in session table for key:" + key);
        }
        cursor.moveToFirst();
        BordeauxSessionManager.Session s = getSessionFromCursor(cursor);
        cursor.close();
        return s;
    }

BordeauxSessionManager[5.1]

这里,我可以看到这个BordeauxSessionManager的类注释:

// This class manages the learning sessions from multiple applications.
// The learning sessions are automatically backed up to the storage.

这里应该是和Application的管理有关。

public IBinder getSessionBinder(Class learnerClass, SessionKey key) {
        if (mSessions.containsKey(key.value)) {
            return mSessions.get(key.value).learner.getBinder();
        }
        // not in memory cache
        try {
            // try to find it in the database
            Session stored = mSessionStorage.getSession(key.value);//调用[4.1]
            if (stored != null) {
                // set the callback, so that we can save the state
                stored.learner.setModelChangeCallback(new LearningUpdateCallback(key.value));
                // found session in the storage, put in the cache
                mSessions.put(key.value, stored);
                return stored.learner.getBinder();
            }

            // if session is not already stored, create a new one.
            Log.i(TAG, "create a new learning session: " + key.value);
            IBordeauxLearner learner =
                    (IBordeauxLearner) learnerClass.getConstructor().newInstance();
            // set the callback, so that we can save the state
            learner.setModelChangeCallback(new LearningUpdateCallback(key.value));
            Session session = new Session();
            session.learnerClass = learnerClass;
            session.learner = learner;
            mSessions.put(key.value, session);
            return learner.getBinder();
        } catch (Exception e) {
            throw new RuntimeException("Can't instantiate class: " +
                                       learnerClass.getName());
        }
    }

但是不懂是干什么的,接着看到这里。

BordeauxSessionManager[5.2]

    // internal unique key that identifies the learning instance.
    // Composed by the package id of the calling process, learning class name
    // and user specified name.
    public SessionKey getSessionKey(String callingUid, Class learnerClass, String name) {
        SessionKey key = new SessionKey();
        key.value = callingUid + "#" + "_" + name + "_" + learnerClass.getName();
        return key;
    }

还是不懂,先放弃了。//TODO
还是回头去去看下这个参的true或者false实现上有啥区别。

SQLiteQueryBuilder.java[6.1]

 // SQLiteDatabase.java[3.2]调用了该方法。
 public static String buildQueryString(
            boolean distinct, String tables, String[] columns, String where,
            String groupBy, String having, String orderBy, String limit) {
	    //这里做的不错,当两个参数为一对都存在才可用的时候要进行校验。
        if (TextUtils.isEmpty(groupBy) && !TextUtils.isEmpty(having)) {
            throw new IllegalArgumentException(
                    "HAVING clauses are only permitted when using a groupBy clause");
        }
        if (!TextUtils.isEmpty(limit) && !sLimitPattern.matcher(limit).matches()) {
            throw new IllegalArgumentException("invalid LIMIT clauses:" + limit);
        }

        StringBuilder query = new StringBuilder(120);

        query.append("SELECT ");
        if (distinct) {
            query.append("DISTINCT ");//区别就是在这里,拼接SQL语句的时候,加了个 DISTINCT
        }
        if (columns != null && columns.length != 0) {
            appendColumns(query, columns);
        } else {
            query.append("* ");
        }
        query.append("FROM ");
        query.append(tables);
        appendClause(query, " WHERE ", where);
        appendClause(query, " GROUP BY ", groupBy);
        appendClause(query, " HAVING ", having);
        appendClause(query, " ORDER BY ", orderBy);
        appendClause(query, " LIMIT ", limit);

        return query.toString();
    }

最后发现 distinct 为 true 的时候,给查询的 SQL 语句拼接了一个参数 DISTINCT。搜索下来段英文的解释装个逼。

The SELECT DISTINCT statement is used to return only distinct (different) values.

Inside a table, a column often contains many duplicate values; and sometimes you only want to list the different (distinct) values.

The SELECT DISTINCT statement is used to return only distinct (different) values.

2、cursorFactory 传null了,注释说用 default factory 怎么玩的

首先观察SQLiteDatabase.java[3.2]这个类rawQueryWithFactory方法中cursorFactory传入为null则用 mCursorFactory,这样说明这个mCursorFactory,也就是所说的 default factory。

SQLiteDatabase.java[3.5]

    private SQLiteDatabase(String path, int openFlags, CursorFactory cursorFactory,
            DatabaseErrorHandler errorHandler) {
        mCursorFactory = cursorFactory;//mCursorFactory
        mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
        mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
    }

发现mCursorFactory是构造中继续传入。

SQLiteDatabase.java[3.6]

    /**
     * Open the database according to the flags {@link #OPEN_READWRITE}
     * @param factory an optional factory class that is called to instantiate a
     *            cursor when query is called, or null for default
     * @param flags to control database access mode
     * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption
     * when sqlite reports database corruption
     * @return the newly opened database
     * @throws SQLiteException if the database cannot be opened
     */
    public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,
            DatabaseErrorHandler errorHandler) {
        SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler);
        db.open();
        return db;
    }

SQLiteOpenHelper.java[7.1]

private SQLiteDatabase getDatabaseLocked(boolean writable) {
        if (mDatabase != null) {
            if (!mDatabase.isOpen()) {
                // Darn!  The user closed the database by calling mDatabase.close().
                mDatabase = null;
            } else if (!writable || !mDatabase.isReadOnly()) {
                // The database is already open for business.
                return mDatabase;
            }
        }

        if (mIsInitializing) {
            throw new IllegalStateException("getDatabase called recursively");
        }

        SQLiteDatabase db = mDatabase;
        try {
            mIsInitializing = true;

            if (db != null) {
                if (writable && db.isReadOnly()) {
                    db.reopenReadWrite();
                }
            } else if (mName == null) {
                db = SQLiteDatabase.create(null);
            } else {
                try {
                    if (DEBUG_STRICT_READONLY && !writable) {
                        final String path = mContext.getDatabasePath(mName).getPath();
						//调用了[3.6]
                        db = SQLiteDatabase.openDatabase(path, mFactory,
                                SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                    } else {
                        db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
                                Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
                                mFactory, mErrorHandler);
                    }
                } catch (SQLiteException ex) {
                    if (writable) {
                        throw ex;
                    }
                    Log.e(TAG, "Couldn't open " + mName
                            + " for writing (will try read-only):", ex);
                    final String path = mContext.getDatabasePath(mName).getPath();
					//调用了[3.6]
                    db = SQLiteDatabase.openDatabase(path, mFactory,
                            SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                }
            }

            onConfigure(db);

            final int version = db.getVersion();
            if (version != mNewVersion) {
                if (db.isReadOnly()) {
                    throw new SQLiteException("Can't upgrade read-only database from version " +
                            db.getVersion() + " to " + mNewVersion + ": " + mName);
                }

                db.beginTransaction();
                try {
                    if (version == 0) {
                        onCreate(db);
                    } else {
                        if (version > mNewVersion) {
                            onDowngrade(db, version, mNewVersion);
                        } else {
                            onUpgrade(db, version, mNewVersion);
                        }
                    }
                    db.setVersion(mNewVersion);
                    db.setTransactionSuccessful();
                } finally {
                    db.endTransaction();
                }
            }

            onOpen(db);

            if (db.isReadOnly()) {
                Log.w(TAG, "Opened " + mName + " in read-only mode");
            }

            mDatabase = db;
            return db;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) {
                db.close();
            }
        }
    }

SQLiteOpenHelper.java[7.2]

    public SQLiteDatabase getReadableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(false);
        }
    }

SQLiteOpenHelper.java[7.3]

    public SQLiteDatabase getWritableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(true);
        }
    }

SQLiteOpenHelper.java[7.4]

    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
        this(context, name, factory, version, null);
    }

最后追踪到这里,又回到开头了。我们通常要继承SQLiteOpenHelper,但是发现我们一般在这里传入的就是null,那这个并没有任何实现。

   MyDBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

DatabaseCursorTest[8.1]

  @MediumTest
    public void testRequeryWithAlteredSelectionArgs() throws Exception {
        /**
         * Test the ability of a subclass of SQLiteCursor to change its query arguments.
         */
        populateDefaultTable();

        SQLiteDatabase.CursorFactory factory = new SQLiteDatabase.CursorFactory() {
            public Cursor newCursor(
                    SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable,
                    SQLiteQuery query) {
                return new SQLiteCursor(db, masterQuery, editTable, query) {
                    @Override
                    public boolean requery() {
                        setSelectionArguments(new String[]{"2"});
                        return super.requery();
                    }
                };
            }
        };
	  // 省略  xxx
  }
}

根据SQLiteDirectCursorDriver.java[2.1] ,看到一个测试代码里边有这么个写法,这时候应该大概明白了这个CursorFactory的作用了,实际可以在外部自定义newCursor的实现。
观察到SQLiteDirectCursorDriver.java[2.1] 的代码,发现传入的CursorFactory,new的方式不一样。

SQLiteCursor[9.1]

    /**
     * Execute a query and provide access to its result set through a Cursor
     * interface. For a query such as: {@code SELECT name, birth, phone FROM
     * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
     * phone) would be in the projection argument and everything from
     * {@code FROM} onward would be in the params argument.
     *
     * @param editTable the name of the table used for this query
     * @param query the {@link SQLiteQuery} object associated with this cursor object.
     */
    public SQLiteCursor(SQLiteCursorDriver driver, String editTable, SQLiteQuery query) {
        if (query == null) {
            throw new IllegalArgumentException("query object cannot be null");
        }
        if (StrictMode.vmSqliteObjectLeaksEnabled()) {
            mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
        } else {
            mStackTrace = null;
        }
        mDriver = driver;
        mEditTable = editTable;
        mColumnNameMap = null;
        mQuery = query;

        mColumns = query.getColumnNames();
        mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
    }

SQLiteDirectCursorDriver.java[2.2]

    /**
     * Used to allow returning sub-classes of {@link Cursor} when calling query.
     */
    public interface CursorFactory {
        /**
         * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
         */
        public Cursor newCursor(SQLiteDatabase db,
                SQLiteCursorDriver masterQuery, String editTable,
                SQLiteQuery query);
    }

根据上述接口,我们是不是考虑在进行查询操作时假如有部分特殊的要求,可以自定义实现自己想要的Cursor。

3、最后如何得到我们想要的返回值Cursor?

根据SQLiteCursor[9.1]实际已经知道看到了Cursor实际是我们new出来的。不过在构造中有几个操作。

        mQuery = query;

        mColumns = query.getColumnNames();
        mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);

五、参考资料

SQL SELECT DISTINCT Statement

ANR: "main" prio=5 tid=1 WaitingForGcToComplete

"main" prio=5 tid=1 WaitingForGcToComplete
| group="main" sCount=1 dsCount=0 flags=1 obj=0x747e4600 self=0xf0010000
| sysTid=16849 nice=-10 cgrp=default sched=0/0 handle=0xf39e94a8
| state=S schedstat=( 0 0 0 ) utm=1435 stm=301 core=5 HZ=100
| stack=0xff2b9000-0xff2bb000 stackSize=8MB
| held mutexes=
kernel: (couldn't read /proc/self/task/16849/stack)
native: #00 pc 00019118 /system/lib/libc.so (syscall+28)
native: #1 pc 000b3c05 /system/lib/libart.so (_ZN3art17ConditionVariable16WaitHoldingLocksEPNS_6ThreadE+88)
native: #2 pc 00192c23 /system/lib/libart.so (_ZN3art2gc4Heap25WaitForGcToCompleteLockedENS0_7GcCauseEPNS_6ThreadE+230)
native: #3 pc 0019d63b /system/lib/libart.so (_ZN3art2gc4Heap19WaitForGcToCompleteENS0_7GcCauseEPNS_6ThreadE+190)
native: #4 pc 0019a2f3 /system/lib/libart.so (_ZN3art2gc4Heap22AllocateInternalWithGcEPNS_6ThreadENS0_13AllocatorTypeEbjPjS5_S5_PNS_6ObjPtrINS_6mirror5ClassEEE+78)
native: #5 pc 003b3009 /system/lib/libart.so (artAllocObjectFromCodeInitializedRegionTLAB+228)
native: #6 pc 003e036b /system/lib/libart.so (art_quick_alloc_object_initialized_region_tlab+74)
native: #7 pc 00000e17 /dev/ashmem/dalvik-jit-code-cache (deleted) (Java_com_xtc_log_util_StackUtils_makeStackInfo__IIJ+198)
at com.xtc.log.util.StackUtils.makeStackInfo(StackUtils.java:23)
at com.xtc.log.util.StackUtils.makeAndroidStackInfo(StackUtils.java:59)
at com.xtc.log.xlog.Xlogger.log(Xlogger.java:249)
at com.xtc.log.Log.i(Log.java:33)
at com.xtc.log.LogUtil.i(LogUtil.java:56)
at com.xtc.watch.receiver.SystemReceiver.onReceive(SystemReceiver.java:83)
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_51571(LoadedApk.java:1304)
at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.$m$0(unavailable:-1)
at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.run(unavailable:-1)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6665)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)

详细

traces(5).txt

image

image

搜索发现:

"FinalizerDaemon" daemon prio=5 tid=5 WaitingPerformingGc
  | group="system" sCount=1 dsCount=0 flags=1 obj=0x12c8a550 self=0xe36fce00
  | sysTid=16856 nice=4 cgrp=default sched=0/0 handle=0xd40dd970
  | state=R schedstat=( 0 0 0 ) utm=1221 stm=58 core=6 HZ=100
  | stack=0xd3fdb000-0xd3fdd000 stackSize=1038KB
  | held mutexes= "mutator lock"(shared held)
  kernel: (couldn't read /proc/self/task/16856/stack)
  native: #00 pc 0017341a  /system/lib/libart.so (_ZN3art2gc9collector17ConcurrentCopying19ProcessMarkStackRefEPNS_6mirror6ObjectE+129)
  native: #01 pc 00172f3b  /system/lib/libart.so (_ZN3art2gc9collector17ConcurrentCopying20ProcessMarkStackOnceEv+402)
  native: #02 pc 00172d9b  /system/lib/libart.so (_ZN3art2gc9collector17ConcurrentCopying16ProcessMarkStackEv+18)
  native: #03 pc 0016e555  /system/lib/libart.so (_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv+456)
  native: #04 pc 0016db35  /system/lib/libart.so (_ZN3art2gc9collector17ConcurrentCopying9RunPhasesEv+540)
  native: #05 pc 0017cbc5  /system/lib/libart.so (_ZN3art2gc9collector16GarbageCollector3RunENS0_7GcCauseEb+268)
  native: #06 pc 001979ef  /system/lib/libart.so (_ZN3art2gc4Heap22CollectGarbageInternalENS0_9collector6GcTypeENS0_7GcCauseEb+2726)
  native: #07 pc 0019b325  /system/lib/libart.so (_ZN3art2gc4Heap22AllocateInternalWithGcEPNS_6ThreadENS0_13AllocatorTypeEbjPjS5_S5_PNS_6ObjPtrINS_6mirror5ClassEEE+4224)
  native: #08 pc 003b3009  /system/lib/libart.so (artAllocObjectFromCodeInitializedRegionTLAB+228)
  native: #09 pc 003e036b  /system/lib/libart.so (art_quick_alloc_object_initialized_region_tlab+74)
  native: #10 pc 014b6921  /system/framework/arm/boot-framework.oat (Java_com_android_internal_os_BinderInternal_00024GcWatcher_finalize__+336)
  at com.android.internal.os.BinderInternal$GcWatcher.finalize(BinderInternal.java:53)
  at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250)
  at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237)
  at java.lang.Daemons$Daemon.run(Daemons.java:103)
  at java.lang.Thread.run(Thread.java:764)

Toast Show的时候出现 BadTokenException: Unable to add window -- token

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@8bb205c is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:812)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:361)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.widget.Toast$TN.handleShow(Toast.java:489)
at android.widget.Toast$TN$2.handleMessage(Toast.java:360)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6455)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1134)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)

使用hanlderThread时出现了NullProintException

     HandlerThread handlerThread = new HandlerThread("timer-scheduler-thread");
    handlerThread.start();// 这里忘记调用就异常了
    mHandler = new Handler(handlerThread.getLooper())

Caused by: java.lang.NullPointerException: Attempt to read from field 'android.os.MessageQueue android.os.Looper.mQueue' on a null object reference
at android.os.Handler.(Handler.java:238)
at android.os.Handler.(Handler.java:146)
at com.xtc.watch.scheduler.HandlerScheduler$1.(HandlerScheduler.java:0)
at com.xtc.watch.scheduler.HandlerScheduler.initHandler(HandlerScheduler.java:24)

ExceptionInInitializerError

java.lang.ExceptionInInitializerError
at com.xtc.im.phone.thirdpush.c$1.onSuccess(Unknown Source)
at com.umeng.message.UmengMessageCallbackHandlerService.onHandleIntent(Unknown Source)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
Caused by: java.lang.RuntimeException: android.os.DeadObjectException
at android.os.storage.StorageManager.getVolumeList(StorageManager.java:886)
at android.os.Environment$UserEnvironment.getExternalDirs(Environment.java:103)
at android.os.Environment.getExternalStorageDirectory(Environment.java:360)
at com.xtc.im.core.push.store.SDCardFile.(Unknown Source)
... 6 more
Caused by: android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:503)
at android.content.pm.IPackageManager$Stub$Proxy.getPackageUid(IPackageManager.java:2235)
at android.os.storage.StorageManager.getVolumeList(StorageManager.java:880)
... 9 more
java.lang.RuntimeException: android.os.DeadObjectException
at android.os.storage.StorageManager.getVolumeList(StorageManager.java:886)
at android.os.Environment$UserEnvironment.getExternalDirs(Environment.java:103)
at android.os.Environment.getExternalStorageDirectory(Environment.java:360)
at com.xtc.im.core.push.store.SDCardFile.(Unknown Source)
at com.xtc.im.phone.thirdpush.c$1.onSuccess(Unknown Source)
at com.umeng.message.UmengMessageCallbackHandlerService.onHandleIntent(Unknown Source)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
Caused by: android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:503)
at android.content.pm.IPackageManager$Stub$Proxy.getPackageUid(IPackageManager.java:2235)
at android.os.storage.StorageManager.getVolumeList(StorageManager.java:880)
... 9 more
android.os.DeadObjectException
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:503)
at android.content.pm.IPackageManager$Stub$Proxy.getPackageUid(IPackageManager.java:2235)
at android.os.storage.StorageManager.getVolumeList(StorageManager.java:880)
at android.os.Environment$UserEnvironment.getExternalDirs(Environment.java:103)
at android.os.Environment.getExternalStorageDirectory(Environment.java:360)
at com.xtc.im.core.push.store.SDCardFile.(Unknown Source)
at com.xtc.im.phone.thirdpush.c$1.onSuccess(Unknown Source)
at com.umeng.message.UmengMessageCallbackHandlerService.onHandleIntent(Unknown Source)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)

image

image

Json转换问题

使用jackson进行Json解析出现崩溃,奇怪的是在魅族Pro5出现了该问题,其他机器正常

03-15 14:22:39.882 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   native: #11 pc 003f483f  /system/lib/libart.so (_ZN3art25JniMethodEndWithReferenceEP8_jobjectjPNS_6ThreadE+102)
03-15 14:22:39.882 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   native: #12 pc 0008ed03  /data/dalvik-cache/arm/system@framework@boot.oat (Java_java_lang_reflect_Constructor_getDeclaredAnnotations__+86)
03-15 14:22:39.882 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at java.lang.reflect.Constructor.getDeclaredAnnotations!(Native method)
03-15 14:22:39.882 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.util.ClassUtil$Ctor.getDeclaredAnnotations(ClassUtil.java:1170)
03-15 14:22:39.882 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.introspect.AnnotatedClass._constructNonDefaultConstructor(AnnotatedClass.java:933)
03-15 14:22:39.882 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.introspect.AnnotatedClass.resolveCreators(AnnotatedClass.java:440)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.introspect.AnnotatedClass.getConstructors(AnnotatedClass.java:306)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:410)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:285)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getJsonValueMethod(POJOPropertiesCollector.java:169)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findJsonValueMethod(BasicBeanDescription.java:222)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByAnnotations(BasicSerializerFactory.java:349)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:208)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:157)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1215)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   - locked <0x0b90d435> (a com.fasterxml.jackson.databind.ser.SerializerCache)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1167)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:490)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap.findAndAddSecondarySerializer(PropertySerializerMap.java:90)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer._findAndAddDynamic(ObjectArraySerializer.java:394)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:253)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:216)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:26)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:256)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:216)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:26)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3613)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2962)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.xtc.watch.util.JSONUtil.toJSON(JSONUtil.java:62)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.xtc.watch.receiver.im.business.ModelConvert.toImMessageData(ModelConvert.java:96)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.xtc.watch.view.weichat.WeiChatHandler.dealWeiChatInfo(WeiChatHandler.java:732)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.xtc.watch.WatchSystemService.translateImMsg(WatchSystemService.java:221)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.xtc.watch.WatchSystemService.onStartCommand(WatchSystemService.java:184)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3433)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at android.app.ActivityThread.-wrap21(ActivityThread.java:-1)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1670)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at android.os.Handler.dispatchMessage(Handler.java:102)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at android.os.Looper.loop(Looper.java:154)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at android.app.ActivityThread.main(ActivityThread.java:6243)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at java.lang.reflect.Method.invoke!(Native method)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
03-15 14:22:39.883 10510-10510/com.xtc.watch A/art: art/runtime/runtime.cc:403]   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802)

调用的方法

public class JSONUtil {

    private static String TAG = JSONUtil.class.getName();

    private static ObjectMapper mapper = new ObjectMapper();

    static {
        //对于为null的字段不进行序列化
        mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
        //对于未知属性不进行反序列化
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //无论对象中的值只有不为null的才进行序列化
        mapper.setSerializationInclusion(Include.NON_NULL);

        mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
    }
 /**
     * 把对象转化成json字符串
     *
     * @param obj
     * @return
     */
    public static String toJSON(Object obj) {
        if (obj == null) {
            return null;
        }

        Writer write = new StringWriter();
        try {
            mapper.writeValue(write, obj);
        } catch (JsonGenerationException e) {
            LogUtil.e(TAG, e.toString() + obj);
        } catch (JsonMappingException e) {
            LogUtil.e(TAG, e.toString() + obj);
        } catch (IOException e) {
            LogUtil.e(TAG, e.toString() + obj);
        }
        return write.toString();
    }

    /**
     * JSON字符串转成对象
     *
     * @param jsonStr
     * @param classType
     * @return
     */
    public static <T> T fromJSON(String jsonStr, Class<T> classType) {
        if (TextUtils.isEmpty(jsonStr)) {
            return null;
        }

        T t = null;
        try {
            t = mapper.readValue(jsonStr.getBytes(Constants.CHARSET_UTF_8), classType);
        } catch (JsonParseException e) {
            LogUtil.e(TAG, e.toString() + ", jsonStr:" + jsonStr + ", classType:" + classType.getName());
        } catch (JsonMappingException e) {
            LogUtil.e(TAG, e.toString() + ", jsonStr:" + jsonStr + ", classType:" + classType.getName());
        } catch (IOException e) {
            LogUtil.e(TAG, e.toString() + ", jsonStr:" + jsonStr + ", classType:" + classType.getName());
        }
        return t;
    }
}

换成Gson就OK了

public class GsonUtil {

    public static String toJSON(Object obj) {
        return createGson().toJson(obj);
    }

    public static String toJSON(Object obj, Type type) {
        return createGson().toJson(obj, type);
    }

    public static <T> T fromJSON(String json, Class<T> cls) {
        try {
            return createGson().fromJson(json, cls);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T fromJSON(String json, Type type) {
        try {
            return createGson().fromJson(json, type);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static Gson createGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.serializeNulls();
        return gsonBuilder.create();
    }
}

Android8.0兼容问题

Service启动限制

8.0的service启动如果APP处在后台,(x21在APP启动的那一刻也认为在后台)将受限制,并报异常:

51250 java.lang.IllegalStateException: Not allowed to start service Intent { pkg=com.xtc.watch cmp=com.xtc.watch/.AppInitService }: app is in background uid UidRecord{75dee3c u0a196 CEM idle change:cached procs:1 seq(0,0,0)}

141019 [E][2018-05-17 +8.0 10:45:22.597][10832, 684][IM-Core-PushServiceManager][, init, 103][init error: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.xtc.im.core.push.PushService flg=0x20 pkg=com.xtc.watch cmp=com.xtc.watch/com.xtc.im.core.push.PushService }: app is in background uid UidRecord{433e37b u0a196 CEM idle change:cached procs:1 seq(0,0,0)}

SharedPreferences解析

初始化

SharedPreferencesImpl

  • mFile 实际SharedPreferences数据存储文件,文件后缀名为“.xml”
  • mBackupFile 备份文件,文件后缀名为“.bak”
  • mMap 内存缓存
    SharedPreferencesImpl(File file, int mode) {
        mFile = file;
        mBackupFile = makeBackupFile(file);
        mMode = mode;
        mLoaded = false;
        mMap = null;
        startLoadFromDisk();
    }
  • 如果存在备份文件,则把XML文件删掉,用备份文件来替换
  • 读取xml文件数据赋值给临时的map
  • 如果读到的数据不为null,则赋值给全局的mMap,也就是放到内存缓存中,并把mLoaded置为true
  • 如果map为null,还是给mMap new 一个对象,方便后面使用
    private void loadFromDisk() {
        synchronized (mLock) {
            if (mLoaded) {
                return;
            }
            // 如果存在备份文件,则把XML文件删掉,用备份文件来替换
            if (mBackupFile.exists()) {
                mFile.delete();
                mBackupFile.renameTo(mFile);
            }
        }

        // Debugging
        if (mFile.exists() && !mFile.canRead()) {
            Log.w(TAG, "Attempt to read preferences file " + mFile + " without permission");
        }

        Map map = null;
        StructStat stat = null;
        try {
            stat = Os.stat(mFile.getPath());
            if (mFile.canRead()) {
                BufferedInputStream str = null;
                try {
                    str = new BufferedInputStream(
                            new FileInputStream(mFile), 16*1024);
                    // 将文件里的数据读取赋值给到map内存缓存
                    map = XmlUtils.readMapXml(str);
                } catch (Exception e) {
                    Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);
                } finally {
                    IoUtils.closeQuietly(str);
                }
            }
        } catch (ErrnoException e) {
            /* ignore */
        }

        synchronized (mLock) {
            mLoaded = true;
            if (map != null) {
                mMap = map;
                mStatTimestamp = stat.st_mtim;
                mStatSize = stat.st_size;
            } else {
                mMap = new HashMap<>();
            }
            mLock.notifyAll();
        }
    }

java.lang.IllegalArgumentException: pointerIndex out of range

java.lang.IllegalArgumentException: pointerIndex out of range
android.view.MotionEvent.nativeGetAxisValue(Native Method)
android.view.MotionEvent.getX(MotionEvent.java:2072)
android.support.v4.view.ViewPager.onTouchEvent(SourceFile:2275)
android.view.View.dispatchTouchEvent(View.java:9432)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2663)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2304)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2318)
com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2447)
com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1766)
android.app.Activity.dispatchTouchEvent(Activity.java:2811)

startActivityForResult的坑

在fragment里面用getActivity().startActivityForResult 去启动,那么这个fragment的onActivityResult里面收不到

SharedPreferences多进程的坑

问题背景:

Android 6.0 系统
多进程写同一个SharedPreferences文件
push进程先写数据到data/data/com.xtc.im.phonesample/shared_prefs/com.xtc.im.phonesample.xml,
正常
app主进程再次写数据,这时文件是一样的,会把push进程的数据覆盖掉。

一样的原因是:

    private static SharedPreferences sp;
    private static volatile LocalPreference instance;

    private LocalPreference(Context context) {
        Context application = context.getApplicationContext();
        sp = application.getSharedPreferences(context.getPackageName(), 0);
    }

    public static LocalPreference getInstance(Context context) {
        if (instance == null) {
            synchronized(LocalPreference.class) {
                if (instance == null) {
                    instance = new LocalPreference(context);
                }
            }
        }

        return instance;
    }

    public boolean putString(String key, String value) {
        return this.getEditor().putString(key, value).commit();
    }

``
但是,这里是不同的进程获取这个SP的单列。

Native闪退

06-21 10:36:51.901 18665-18945/com.xtc.watch A/libc: heap corruption detected by dlmalloc_real
06-21 10:36:51.901 18665-18945/com.xtc.watch A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 18945 (Thread-3956)
06-21 10:36:53.581 1241-18958/? E/test: key length=16
06-21 10:36:53.591 1241-18958/? E/test: decodePrivate 22
06-21 10:36:54.051 875-1143/? E/NativeCrashListener: Exception dealing with report
                                                     android.system.ErrnoException: read failed: EAGAIN (Try again)
                                                         at libcore.io.Posix.readBytes(Native Method)
                                                         at libcore.io.Posix.read(Posix.java:165)
                                                         at libcore.io.BlockGuardOs.read(BlockGuardOs.java:230)
                                                         at android.system.Os.read(Os.java:350)
                                                         at com.android.server.am.NativeCrashListener.consumeNativeCrashData(NativeCrashListener.java:240)
                                                         at com.android.server.am.NativeCrashListener.run(NativeCrashListener.java:138)

BindService时异常java.lang.NullPointerException: Attempt to read from field 'long android.os.Parcel.mNativePtr' on a null object reference

#Wed Feb 07 13:05:56 GMT+08:00 2018
STACK_TRACE=java.lang.RuntimeException: Unable to bind to service com.xtc.im.core.push.PushService@33d1d88a with Intent { act=com.xtc.im.core.push.PushService flg=0x20 pkg=com.xtc.watch cmp=com.xtc.watch/com.xtc.im.core.push.PushService (has extras) }: java.lang.NullPointerException: Attempt to read from field 'long android.os.Parcel.mNativePtr' on a null object reference
 android.app.ActivityThread.handleBindService(ActivityThread.java:2880)
 android.app.ActivityThread.access$2000(ActivityThread.java:175)
 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1457)
 android.os.Handler.dispatchMessage(Handler.java:102)
 android.os.Looper.loop(Looper.java:135)
 android.app.ActivityThread.main(ActivityThread.java:5418)
 java.lang.reflect.Method.invoke(Native Method)
 java.lang.reflect.Method.invoke(Method.java:372)
 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1037)
 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: java.lang.NullPointerException: Attempt to read from field 'long android.os.Parcel.mNativePtr' on a null object reference
 android.os.Parcel.appendFrom(Parcel.java:446)
 android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1300)
 android.os.Bundle.writeToParcel(Bundle.java:1034)
 android.os.Parcel.writeBundle(Parcel.java:697)
 android.content.Intent.writeToParcel(Intent.java:7734)
 android.app.ActivityManagerProxy.publishService(ActivityManagerNative.java:3676)
 android.app.ActivityThread.handleBindService(ActivityThread.java:2868)
/r... 9 more
java.lang.NullPointerException: Attempt to read from field 'long android.os.Parcel.mNativePtr' on a null object reference
 android.os.Parcel.appendFrom(Parcel.java:446)
 android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1300)
 android.os.Bundle.writeToParcel(Bundle.java:1034)
 android.os.Parcel.writeBundle(Parcel.java:697)
 android.content.Intent.writeToParcel(Intent.java:7734)
 android.app.ActivityManagerProxy.publishService(ActivityManagerNative.java:3676)
 android.app.ActivityThread.handleBindService(ActivityThread.java:2868)
 android.app.ActivityThread.access$2000(ActivityThread.java:175)
 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1457)
 android.os.Handler.dispatchMessage(Handler.java:102)
 android.os.Looper.loop(Looper.java:135)
 android.app.ActivityThread.main(ActivityThread.java:5418)
 java.lang.reflect.Method.invoke(Native Method)
 java.lang.reflect.Method.invoke(Method.java:372)
 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1037)
 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

java.lang.SecurityException: Unable to start service Intent { xxx }: user 0 is restricted

java.lang.SecurityException: Unable to start service Intent { act=com.xtc.im.app.revive.pushinfo cat=[com.xtc.im] flg=0x20 pkg=com.xtc.watch cmp=com.xtc.watch/com.xtc.im.core.app.bridge.AppReviveService (has extras) }: Unable to launch app com.xtc.watch/10273 for service Intent { act=com.xtc.im.app.revive.pushinfo cat=[com.xtc.im] pkg=com.xtc.watch cmp=com.xtc.watch/com.xtc.im.core.app.bridge.AppReviveService }: user 0 is restricted
	at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1769)
	at android.app.ContextImpl.startService(ContextImpl.java:1742)
	at android.content.ContextWrapper.startService(ContextWrapper.java:527)

Android8.0系统:.RemoteServiceException: Bad notification for startForeground

问题:启动push进程失败

启动的时候发现push进程起来了,但是立即弹出“停止运行”,查看Log有如下异常:

Process: com.xtc.watch:push, PID: 12789
android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1768)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

点击确认,发现Push进程已挂,随后Log出现如下异常:

java.lang.IllegalStateException: Not allowed to start service Intent { act=com.xtc.im.core.push.PushService flg=0x20 pkg=com.xtc.watch cmp=com.xtc.watch/com.xtc.im.core.push.PushService (has extras) }:
app is in background uid UidRecord{1922d78 u0a169 SVC idle change:idle|uncached procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1521)
at android.app.ContextImpl.startService(ContextImpl.java:1477)
at android.content.ContextWrapper.startService(ContextWrapper.java:650)
at com.xtc.im.core.app.bridge.PushServiceManager.init(PushServiceManager.java:104)
at com.xtc.im.core.app.IMCore$16.run(IMCore.java:903)
at java.lang.Thread.run(Thread.java:764)

IM即时通讯SDK网络问题集合

1、 java.net.SocketException: sendto failed: EBADF (Bad file descriptor)

java.net.SocketException: sendto failed: EBADF (Bad file descriptor)
	at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:542)
	at libcore.io.IoBridge.sendto(IoBridge.java:511)
	at java.net.PlainSocketImpl.write(PlainSocketImpl.java:500)

Android 8.0:Not allowed to start service Intent

问题:Android 8.0 系统启动service失败

java.lang.IllegalStateException: Not allowed to start service Intent { act=com.xtc.im.core.push.PushService flg=0x20 pkg=com.xtc.watch cmp=com.xtc.watch/com.xtc.im.core.push.PushService (has extras) }:
app is in background uid UidRecord{1922d78 u0a169 SVC idle change:idle|uncached procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1521)
at android.app.ContextImpl.startService(ContextImpl.java:1477)
at android.content.ContextWrapper.startService(ContextWrapper.java:650)
at com.xtc.im.core.app.bridge.PushServiceManager.init(PushServiceManager.java:104)
at com.xtc.im.core.app.IMCore$16.run(IMCore.java:903)
at java.lang.Thread.run(Thread.java:764)

java.lang.IllegalStateException: Fragment already added

STACK_TRACE=java.lang.IllegalStateException: Fragment already added: LocationMainFragment
at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1891)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:760)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5401)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:919)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:714)

java.util.concurrent.RejectedExecutionException

java.util.concurrent.RejectedExecutionException: Task com.xtc.im.core.common.task.RealCall$AsyncCall@f0b58eb rejected from java.util.concurrent.ThreadPoolExecutor@daea648[Shutting down, pool size = 64, active threads = 64, queued tasks = 0, completed tasks = 8]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2049)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:814)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1360)

.EventBus.register异常: Didn't find class "android.os.PersistableBundle"

java.lang.NoClassDefFoundError: android/os/PersistableBundle
	at java.lang.Class.getDeclaredMethods(Native Method)
	at java.lang.Class.getPublicMethodsRecursive(Class.java:894)
	at java.lang.Class.getMethods(Class.java:877)
	at org.greenrobot.eventbus.SubscriberMethodFinder.findUsingReflectionInSingleClass(SubscriberMethodFinder.java:157)
	at org.greenrobot.eventbus.SubscriberMethodFinder.findUsingInfo(SubscriberMethodFinder.java:88)
	at org.greenrobot.eventbus.SubscriberMethodFinder.findSubscriberMethods(SubscriberMethodFinder.java:64)
	at org.greenrobot.eventbus.EventBus.register(EventBus.java:136)
	at com.xtc.watch.view.location.view.impl.LocationMainActivity.onCreate(LocationMainActivity.java:300)
	at android.app.Activity.performCreate(Activity.java:5355)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1089)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2171)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
	at android.app.ActivityThread.access$800(ActivityThread.java:140)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202)
	at android.os.Handler.dispatchMessage(Handler.java:102)
	at android.os.Looper.loop(Looper.java:136)
	at android.app.ActivityThread.main(ActivityThread.java:5113)
	at java.lang.reflect.Method.invokeNative(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:515)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:780)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:596)
	at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.os.PersistableBundle" on path: DexPathList[[zip file "/data/app/com.xtc.watch-1.apk", zip file "/data/data/com.xtc.watch/code_cache/secondary-dexes/com.xtc.watch-1.apk.classes2.zip", zip file "/data/data/com.xtc.watch/code_cache/secondary-dexes/com.xtc.watch-1.apk.classes3.zip", zip file "/data/data/com.xtc.watch/code_cache/secondary-dexes/com.xtc.watch-1.apk.classes4.zip"],nativeLibraryDirectories=[/data/app-lib/com.xtc.watch-1, /vendor/lib, /system/lib]]
	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
	... 22 more

代码

  @override
  public void onSaveInstanceState(Bundle outState) {
       super.onSaveInstanceState(outState);
      EventBus.getDefault().register(MainActivity.this);
  }
    @Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        LogUtil.i(TAG, "xxx onSaveInstanceState...");
    }

CursorWindowAllocationException

android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed.
at android.database.CursorWindow.(CursorWindow.java:104)
at android.database.CursorWindow.(CursorWindow.java:126)
at net.sqlcipher.CursorWindow.(CursorWindow.java:54)
at net.sqlcipher.database.SQLiteCursor.fillWindow(SQLiteCursor.java:288)
at net.sqlcipher.database.SQLiteCursor.getCount(SQLiteCursor.java:280)
at net.sqlcipher.AbstractCursor.moveToPosition(AbstractCursor.java:178)
at net.sqlcipher.AbstractCursor.moveToFirst(AbstractCursor.java:222)
at android.database.CursorWrapper.moveToFirst(CursorWrapper.java:65)
at com.j256.ormlite.sqlcipher.android.AndroidCompiledStatement.getCursor(AndroidCompiledStatement.java:181)
at com.j256.ormlite.sqlcipher.android.AndroidCompiledStatement.runQuery(AndroidCompiledStatement.java:65)
at com.j256.ormlite.stmt.SelectIterator.(SelectIterator.java:55)
at com.j256.ormlite.stmt.StatementExecutor.buildIterator(StatementExecutor.java:247)
at com.j256.ormlite.stmt.StatementExecutor.query(StatementExecutor.java:196)
at com.j256.ormlite.dao.BaseDaoImpl.query(BaseDaoImpl.java:265)
at com.j256.ormlite.stmt.QueryBuilder.query(QueryBuilder.java:361)

SQLite异常整理

android.database.sqlite.SQLiteDiskIOException: disk I/O error - SQLITE_IOERR_WRITE (Sqlite code 778), (OS error - 9:Bad file descriptor)
at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:563)
at android.database.sqlite.SQLiteSession.endTransactionUnchecked(SQLiteSession.java:437)
at android.database.sqlite.SQLiteSession.endTransaction(SQLiteSession.java:401)
at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:541)
at com.xtc.im.core.push.store.dao.ServerConfigDao.update(Unknown Source)
at com.xtc.im.core.push.domain.DomainManager.updateOnConnectSuccess(Unknown Source)
at com.xtc.im.core.push.PushService$1$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:743)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:150)
at android.os.HandlerThread.run(HandlerThread.java:61)

java.lang.IllegalStateException: The specified child already has a parent.

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xtc.watch/com.xtc.watch.view.home.activity.XtcHomeActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2200)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2249)
	at android.app.ActivityThread.access$800(ActivityThread.java:141)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1212)
	at android.os.Handler.dispatchMessage(Handler.java:102)
	at android.os.Looper.loop(Looper.java:136)
	at android.app.ActivityThread.main(ActivityThread.java:5113)
	at java.lang.reflect.Method.invokeNative(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:515)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
	at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
	at android.view.ViewGroup.addViewInner(ViewGroup.java:3564)
	at android.view.ViewGroup.addView(ViewGroup.java:3417)
	at android.view.ViewGroup.addView(ViewGroup.java:3362)
	at android.view.ViewGroup.addView(ViewGroup.java:3338)
	at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1434)
	at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
	at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
	at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3244)
	at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3200)
	at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:195)
	at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:597)
	at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
	at android.app.Activity.performStart(Activity.java:5252)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2173)
	... 11 more

Android系统版本兼容ReflectiveOperationException问题

反射获取getTag接口报ReflectiveOperationException

private static String getWakeLockTag(PowerManager.WakeLock wakeLock) {
        String tag = "Default-WakeLock-Tag";
        if (wakeLock == null) {
            return tag;
        }
        try {
            Method getTagMethod = wakeLock.getClass().getDeclaredMethod("getTag");
            getTagMethod.setAccessible(true);
            tag = (String) getTagMethod.invoke(wakeLock, (Object[]) null);
        } catch (ClassNotFoundExceptione) {
            LogUtil.w(TAG,e);
        } 
        return tag;
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.