53

最新の API レベル - 16 でのみ利用可能ないくつかの関数とクラスを使用するアプリを作成していますが、API レベル 15 のデバイスでエラーなしで実行したいと考えています。

いくつかの例を使用してみましょう。新しいクラス: Android.widget.Advanceable、および新しい/名前が変更されたメソッド: View.setBackground():

私はこのようなことができます:

Advanceable myAdvanceable = ...;

if (android.os.Build.VERSION.SDK_INT >= 16)
{
    myView.setBackground(...);
    myAdvanceable.advance();
}
else
{
    myView.setBackgroundDrawable(...); // The old function name.
    // Don't bother advancing advanceables.
}

また、minSdk を 15 に設定し、ビルド ターゲットを 16 に設定すると (つまり、[プロジェクト プロパティ] -> [Android] で)、実際にはエラーなしでコンパイルされます。少なくとも時々。Eclipse はエラーについて少し確率論的であり、「setBackground() は API レベル >= 16 でのみ使用可能です」などと言うことがありますが、プロジェクトをきれいにすると、これらのエラーは魔法のように消えます。

だから私の質問は、私はこれをすることを許されていますか? API レベル 15 のデバイスでコードを実行するとクラッシュしませんか? 実際に 16 コードに到達した場合にのみクラッシュしますか? Eclipse がビルドを止めないのはなぜですか?

編集 1

答えてくれてありがとう、私は質問が本当にあるべきだと思います: 新しい API の使用について lint が警告しないのはなぜですか?

マニフェストにこれがあり、API レベル 16 関数を使用していますが、それでも警告は表示されません。

<uses-sdk android:minSdkVersion="15"
    android:targetSdkVersion="16"/>

また、クラス全体が API レベル ( Advanceable. 具体的には、それらをメンバー変数として使用する場合。

編集 2

答えは「Eclipse は地獄のようにバグが多い」であることが判明しましたが、Nico の答えも非常に役に立ちました。

4

3 に答える 3

74

インライン Api エラーは ADT にとって新しいものです。Eclipse は Lint を実行し (おそらく他の何かを推測します)、コードを分析し、それらのエラー/警告をインラインに配置します。最適化やベスト プラクティスに関する警告やヒントがある場合は、xml レイアウトにも同じことが当てはまります。注釈を使用して、クラスまたは特定のメソッドでこれらのエラーを抑制することができます。

@TargetApi(16)
@SuppressLint("NewApi")

ここに置いたサンプル コードには問題があります。API レベル チェックのほかに、API < 16 では機能しないコードに Advanceable のインスタンスがあるため、API レベルのチェックは新しいメソッドを呼び出すときにのみ役立ちますが、できません。 IF ブロック外の新しい API クラスを参照します。

私が受け入れられるアプローチの 1 つは、抽象クラスと 2 つの実装を作成し、静的メソッドでファクトリ クラスを使用して正しい実装をインスタンス化することです。

たとえば、いくつかの新しい API クラスとメソッドを内部で使用するビューを作成するには、次のものが必要です。

1 - 抽象クラスを作成します:

public abstract class CustomView {
    public abstract void doSomething();
}
  • すべての API と互換性のある共通の実装
  • ここで抽象メソッドを定義して実装を分割します

2 - 従来の実装

public class CustomLegacyView extends CustomView {
    public void doSomething(){
        //implement api < 16
    }
}
  • API < 16 の抽象メソッドを実装する

3 - API 16 の実装

@TargetApi(16)
public class CustomL16View extends CustomView {

    Advanceable myAdvanceable;

    public void doSomething(){
        //implement api >= 16
    }
}
  • アノテーション @TargetApi(16) を使用
  • API >= 16 の抽象メソッドを実装する
  • ここでレベル 16 クラスを参照できます (CustomView では参照できません)。

4 - ファクトリ クラス

public class ViewFactory {

    public static CustomView getCustomView(Context context) {

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            return new CustomL16View(context);
        }else{
            return new CustomLegacyView(context);
        }

    }
}
于 2012-07-21T14:48:45.103 に答える
3

新しいビルド ターゲットを使用し、適切な状況で新しい API が呼び出されることを保証するのが一般的な方法です。Google は@TargetApi()、ADT 17 以降、条件付きで読み込まれるコードのローカル オーバーライドを指定するための注釈を追加しました。

詳細については、 Lint API チェックを参照してください。

于 2012-07-21T14:08:14.210 に答える
-3

1.ターゲットとするデバイスの種類と 、実行する最小の Api バージョンを定義するための属性がTarget Apiあります。Minimum SDK

2. Target Apiアプリがフル機能実行されるものになりますが、下位の API バージョンには上位バージョンの機能が含まれていない可能性があるため、いくつかの妥協を伴ってアプリが実行されMinimum SDKます。

于 2012-07-21T14:42:18.727 に答える