代码之家  ›  专栏  ›  技术社区  ›  arlomedia

突然错过了很多Android 4的课程

  •  0
  • arlomedia  · 技术社区  · 6 年前

    我的应用程序在android4.0.3及更高版本上运行多年了。随着最近的一次小更新,它突然开始在android4.x设备上崩溃。当我在android4上调试它时,它的构建和安装都很好,但是控制台从一开始就有很多错误

    W/dalvikvm: VFY: unable to find class referenced in signature (Landroid/media/midi/MidiDeviceInfo;)
    I/dalvikvm: Failed resolving Lcom/arlomedia/myapp/App$4; interface 113 'Landroid/media/midi/MidiManager$OnDeviceOpenedListener;'
    W/dalvikvm: Link of class 'Lcom/arlomedia/myapp/App$4;' failed
    E/dalvikvm: Could not find class 'com.arlomedia.myapp.App$4', referenced from method com.arlomedia.myapp.App.addMidiPorts
    W/dalvikvm: VFY: unable to resolve new-instance 447 (Lcom/arlomedia/myapp/App$4;) in Lcom/arlomedia/myapp/App;
    D/dalvikvm: VFY: replacing opcode 0x22 at 0x0007
    

    these instructions

    我的第二个理论是,android6中添加的middeviceinfo类的使用在android4上造成了一个问题。但是,我使用的是版本检查和 @TargetApi(24)

    这些理论中有一个听起来是对的,还是像其他问题?

    顺便问一下,“找不到签名中引用的类”到底是什么意思——方法签名?我确实有一些方法使用middeviceinfo类型的参数,但是我用 @目标API(24)

    多亏了homerman的提示,我发现方法的数量不是问题所在。这让我回到了MIDI兼容性,但是我正在查看与上一版本的差异,我没有看到对MIDI代码的任何更改。我还应该找什么?

    更新2

    自从上一个版本以来,我找不到任何与差异相关的东西,所以我从风投那里查看了上一个版本并运行了它,它运行得很好。但我注意到,在该版本的logcat中,MIDI类出现了相同的错误。所以看起来这些并不是问题的一部分。我想这正是Android在运行到新类时所做的。我一直在比较上一个好版本和当前版本之间的logcats,然后我看到了区别:我最近在我的一个类中添加了一个onscrollchangesellent。这又产生了一批上一个应用程序版本中没有的类错误。当我删除这个新功能后,这个应用程序在android4上又可以正常运行了。

    所以问题是:我有这样一个类定义:

    public class DocumentViewer extends RelativeLayout implements View.OnScrollChangeListener {
    
        if (Build.VERSION.SDK_INT >= 23) {
            textView.setOnScrollChangeListener(this);
        }
    
        @Override
        public void onScrollChange(final View scrollView, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            Log.d("onScrollChange", "scroll changed: " + scrollY);
        }
    
    }
    

    很明显 View.OnScrollChangeListener

    显然,android5优雅地忽略了这个不受支持的引用,但android4没有。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Ben P.    6 年前

    这个 View.OnScrollChangeListener 接口是在API级别23中添加的。这意味着你的类定义已经是个问题了;如果这个类在23之前加载过,你会崩溃的。

    public interface DocumentViewer {
        // interface methods
    }
    
    public class DocumentViewPre23 extends RelativeLayout implements DocumentViewer {
        // interface methods
    }
    
    public class DocumentViewer23 extends RelativeLayout implements DocumentViewer, View.OnScrollChangeListener {
        // interface methods
    }
    

    然后你就可以有

    public static DocumentViewer getDocumentViewer() {
        if (Build.VERSION.SDK_INT >= 23) {
            return new DocumentViewer23();
        } else {
            return new DocumentViewerPre23();
        }
    }
    

    android支持库经常这样做,这是值得的。下面是一个来自 ActionBarDrawerToggle

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        mActivityImpl = new JellybeanMr2Delegate(activity);
    } else {
        mActivityImpl = new IcsDelegate(activity);
    }
    
    public interface Delegate {
        ...
    }
    
    @RequiresApi(18)
    private static class JellybeanMr2Delegate implements Delegate {
        ...
    }
    
    private static class IcsDelegate implements Delegate {
        ...
    }
    
        2
  •  0
  •   arlomedia    6 年前

    // this was the original class and I added scrollViewDidScroll() to keep all my related code in one class
    public class DocumentViewer extends RelativeLayout {
    
        if (Build.VERSION.SDK_INT >= 23) {
            if (this instanceof DocumentViewerExtras) {
                // assign the listener on supported devices
                DocumentViewerExtras thisExtras = (DocumentViewerExtras)this;
                textView.setOnScrollChangeListener(thisExtras);
            }
        }
    
        public void scrollViewDidScroll(final View scrollView, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            // do something with the scroll results
        }
    
    }
    
    // this is a new class that adds OnScrollChangeListener on supported devices
    @RequiresApi(23)
    public class DocumentViewerExtras extends DocumentViewer implements View.OnScrollChangeListener {
    
        public DocumentViewerExtras(Fragment fragment) {
            super(fragment);
        }
    
        @Override
        public void onScrollChange(final View scrollView, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            this.scrollViewDidScroll(scrollView, scrollX, scrollY, oldScrollX, oldScrollY);
        }
    
    }
    
    // this method instantiates the best available class
    public DocumentViewer getDocumentViewer(Fragment fragment) {
        if (Build.VERSION.SDK_INT >= 23) {
            return new DocumentViewerExtras(fragment);
        } else {
            return new DocumentViewer(fragment);
        }
    }
    
    // this is how I get a new instance of the class
    DocumentViewer documentViewer = getDocumentViewer(this);