Android の上位バージョンで遭遇する落とし穴

ここでは、開発プロセス (継続的な更新) 中に Android の上位バージョンで発生するいくつかの問題の概要を示します。
1. サードパーティからログインすると、Apache で
エラーが発生します。
パス上にクラス「org.apache.http.conn.scheme.SchemeRegistry」が見つかりませんでした。
その後、クラッシュします。

解決策:
Android 6.0 では、Apache HTTP クライアントのサポートがキャンセルされました。Android 9 以降、このコンテンツ ライブラリはブートクラスパスから削除され、デフォルトではアプリで使用できなくなります。Apache HTTP クライアントを引き続き使用するために、Android 9 以降をターゲットとするアプリは、アプリケーション ノードの下の AndroidManifest.xml に以下を追加できます。

<uses-library
    android:name="org.apache.http.legacy"
    android:required="false" />

注: org.apache.http.legacy ライブラリは API レベル 24 より低いデバイスでは利用できないため、最小 SDK バージョンが 23 以下のアプリには android:required="false" 属性が必要です。

2. HTTP
序文: ユーザー データとデバイスのセキュリティを確保するため、Google は次世代 Android システム (Android P) のアプリケーションにデフォルトで暗号化された接続を使用することを要求します。これは、Android P がアプリケーションによる暗号化されていない接続の使用をすべて禁止することを意味します。したがって、Android P システムを実行している Android デバイスは、トラフィックを受信するか送信するかに関係なく、将来的にはトラフィックを明確に送信できなくなり、次世代 (トランスポート層セキュリティ) トランスポート層セキュリティ プロトコルを使用する必要があります。Android Nougat と Oreo は、影響を受けないこと。
したがって、Android P で http リクエストに HttpUrlConnection を使用すると、次の例外が発生します:
W/System.err: java.io.IOException: **** へのクリアテキスト HTTP トラフィックは許可されません
。OKHttp リクエストを使用すると、次の例外が発生します。発生:
java.net.UnknownServiceException: CLEARTEXT 通信 ** ネットワーク セキュリティ ポリシーによって許可されていません
Android P システム デバイスでは、アプリケーションが暗号化されていないプレーンテキスト トラフィックで http ネットワーク リクエストを使用する場合、アプリケーションはネットワーク リクエストを行うことができず、https は行われません。同様に、アプリケーションにネストされた Web ビューがある場合、Web ビューは https リクエストのみを使用できます。

この問題を解決するには、次の 3 つの解決策があります。
(1) APP が https リクエストに切り替える
(2) targetSdkVersion が 27 を下回る
(3) ネットワーク セキュリティ設定を変更する

最初の 2 つの方法は理解と実装が簡単ですが、3 つ目の方法であるネットワーク セキュリティ構成を変更する方法について詳しく説明します。
1. res フォルダーの下に xml フォルダーを作成し、次の内容を含む network_security_config.xml ファイルを作成します。

<?xml バージョン="1.0" エンコーディング="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

2. 次に、AndroidManifest.xml ファイルの application タグに次の属性を追加します。

<application
...
 android:networkSecurityConfig="@xml/network_security_config"
...
/>

完了すると、アプリはネットワークにアクセスできるようになります。
(4) AndroidManifest.xml 設定ファイルのタグ内に
android:usesCleartextTraffic="true"を直接挿入します
。 3. 読み込み・書き込み
Android Q バージョン以降の端末では、ファイルの読み込み・書き込みに失敗する場合があります。これは、Android Q がデフォルトでサンドボックス モードをオンにするため、ファイルの読み書きに失敗するためであり、動的許可アプリケーションを使用する場合は AndroidManifest.xml に追加する必要があります。

android:requestLegacyExternalStorage="true"

4. Android WorldWind のスクリーンショット
Worldwind は GLSurfaceView から継承されます。GLSurfaceView が画像をインターセプトする場合、従来の方法は機能しないことがよくあります。GLSurfaceView.getDrawingCache() などのメソッドを使用すると、多くの場合、真っ黒な画像が生成されることがわかります。これは、GLSurfaceView と SurfaceView の両方に透明なキャッシュ領域があるためです。多くの場合、単なるこの透過的なキャッシュ領域です。

解決策:
方法 1:
次の方法は stackoverflow で見た方法であり、個人的なテストには実行可能です。

private Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl) {
    
    
        int bitmapBuffer[] = new int[w * h];
        int bitmapSource[] = new int[w * h];
        IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
        intBuffer.position(0);
        try {
    
    
            gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE,
                    intBuffer);
            int offset1, offset2;
            for (int i = 0; i < h; i++) {
    
    
                offset1 = i * w;
                offset2 = (h - i - 1) * w;
                for (int j = 0; j < w; j++) {
    
    
                    int texturePixel = bitmapBuffer[offset1 + j];
                    int blue = (texturePixel >> 16) & 0xff;
                    int red = (texturePixel << 16) & 0x00ff0000;
                    int pixel = (texturePixel & 0xff00ff00) | red | blue;
                    bitmapSource[offset2 + j] = pixel;
                }
            }
        } catch (GLException e) {
    
    
            return null;
        }
        return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
    }

スクリーンショットコード:

@Override
public void onDrawFrame(GL10 gl) {
    
    
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    // 获取GLSurfaceView的图片并保存
    if (isTakePicture) {
    
    
        Bitmap bmp = createBitmapFromGLSurface(0, 0, mOutputWidth,
                mOutputHeight, gl);
        isTakePicture = false;
}

onDrawFrame メソッドは常に呼び出されるため、スクリーンショットの論理条件を制御する必要があります。

方法 2:
この方法も、私たちのプロジェクトで写真をキャプチャするために使用された方法の 1 つであり、使用することもできます。

private ByteBuffer mCaptureBuffer;
 
@Override
public void onDrawFrame(GL10 arg0) {
    
    
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    surfaceTexture.updateTexImage();
    draw();
    if (isTakePic) {
    
    
        mCaptureBuffer.rewind();
        GLES20.glReadPixels(0, 0, mOutputWidth, mOutputHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
                mCaptureBuffer);
        isTakePic = false;
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                mCaptureBuffer.rewind();
                mBitmap.copyPixelsFromBuffer(mCaptureBuffer);
                String imageName = "Image_" + System.currentTimeMillis() + ".jpg";
                BitmapUtils.saveBitmap(mBitmap, "/sdcard/face/", imageName);
            }
        }).start();
    }
}
 
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    
    
    mOutputWidth = width;
    mOutputHeight = height;
    mCaptureBuffer = ByteBuffer.allocate(mOutputWidth * mOutputHeight * 4);
    mBitmap = Bitmap.createBitmap(mOutputWidth, height, Config.ARGB_8888);
    GLES20.glViewport(0, 0, width, height);
    mFilter.onOutputSizeChanged(width, height);
}

転載アドレス: https://blog.csdn.net/afei__/article/details/51614375
5. Android がフローティング ウィンドウをポップアップし、「ウィンドウ タイプのアクセス許可が拒否されました」と報告する場合の対処方法
Android システムでは、アプリケーションがフローティング ウィンドウをポップアップする必要がある場合、特別な許可を申請する必要があります。

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

Android O より前のシステムでこの権限を申請した後、対応するウィンドウのポップアップ ウィンドウ タイプを設定します。

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_PHONE;

フローティングウィンドウが表示されます。
Android O 以降のバージョンで実行する場合、Google は、申請時にフローティング ウィンドウのタイプを次のようにする必要があると規定しています。

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

フローティングウィンドウを表示することができ、「TYPE_APPLICATION_OVERLAY」がポイントです。そうしないとクラッシュする可能性があります。

ここでは、開発プロセス (継続的な更新) 中に Android の上位バージョンで発生するいくつかの問題の概要を示します。

おすすめ

転載: blog.csdn.net/nanjumufeng/article/details/123252554