2017-07-11 15:08:55 wxz1179503422 阅读数 7574
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57543 人正在学习 去看看 李宁
  • 现在智能家居很火,有很多的云平台提供者,也有很多智能设备提供者,例如智能摄像头,偶然的机会我接触了一款智能摄像头PnP网络摄像头,就下载了他的sdk玩了一下,简单记录一下调用so库踩的坑。
  • PnP网络摄像头的demo是eclipse开发,我就想切换到as上面,我新建项目之后,将so库放在了libs目录下面之后,我不知道怎么处理这个so,找了很久找了解决方法,在appbuild.gradle文件中的android节点里添加下面的代码,就可以引入so库。
//加载so库
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

之后就是调用so库中的native

static {
        //加载so库的时候,需要掐头去尾,去掉lib和.so
        System.loadLibrary("ijkffmpeg");
        System.loadLibrary("vstc2_jni");
    }

这里写图片描述

如果运行起来,报Android:No implementation found for native,如果你是使用别人的so库那多半是因为加载so库的所在的包名路径的问题。
关于错误 Android:No implementation found for native 可以查看这篇文章Android:No implementation found for native
Android Studio使用jni、so库


感谢前辈博主们的分享,加油!

2019-07-03 21:04:12 aa1358075776 阅读数 1066
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57543 人正在学习 去看看 李宁

1.确保项目启动的时候so文件在classpath路径下

2.Native.loadLibrary使用直接加载需要的类  例如:Native.loadLibrary("encryption", Encryption32.class) 加载一个使用c编写的加解密类

2019-08-03 14:15:57 meinanqihao 阅读数 24
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57543 人正在学习 去看看 李宁

 

1,关于native关键字

想必读者已经了解过native关键字了。这里笔者就大致囊括一下,被native关键字修饰的方法叫做本地方法,本地方法和其它方法不一样,本地方法意味着和平台有关,因此使用了native的程序可移植性都不太高。另外native方法在JVM中运行时数据区也和其它方法不一样,它有专门的本地方法栈。native方法主要用于加载文件和动态链接库,由于Java语言无法访问操作系统底层信息(比如:底层硬件设备等),这时候就需要借助C语言来完成了。被native修饰的方法可以被C语言重写。

 

2,使用native关键字

使用步骤

  • Java程序中声明native修饰的方法,类似于abstract修饰的方法,只有方法签名,没有方法实现。编译该java文件,会产生一个.class文件。
  • 使用javah编译上一步产生的class文件,会产生一个.h文件。
  • 写一个.cpp文件实现上一步中.h文件中的方法。
  • 将上一步的.cpp文件编译成动态链接库文件.dll。
  • 最后就可以使用System或是Runtime中的loadLibrary()方法加载上一步的产生的动态连接库文件了。

一. 什么是Native Method

简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。 "A native method is a Java method whose implementation is provided by non-java code." 在定义一个native method时,并不提供实现体(有些像定义一个java interface),因为其实现体是由非java语言在外面实现的。,下面给了一个示例:

 public class IHaveNatives { 
    native public void Native1( int x ) ;
    native static public long Native2() ; 
    native synchronized private float Native3( Object o ) ;
    native void Native4( int[] ary ) throws Exception ;    
 }
  • 和abstract方法很像
  • 标识符native可以与所有其它的java标识符连用,但是abstract除外。这是合理的,因为native暗示这些方法是有实现体的,只不过这些实现体是非java的,但是abstract却显然的指明这些方法无实现体。native与其它java标识符连用时,其意义同非Native Method并无差别,比如native static表明这个方法可以在不产生类的实例时直接调用,这非常方便,比如当你想用一个native method去调用一个C的类库时。上面的第三个方法用到了native synchronized,JVM在进入这个方法的实现体之前会执行同步锁机制(就像java的多线程。)
  • 一个native method方法可以返回任何java类型,包括非基本类型,而且同样可以进行异常控制。这些方法的实现体可以制一个异常并且将其抛出,这一点与java的方法非常相似。当一个native method接收到一些非基本类型时如Object或一个整型数组时,这个方法可以访问这非些基本型的内部,但是这将使这个native方法依赖于你所访问的java类的实现。有一点要牢牢记住:我们可以在一个native method的本地实现中访问所有的java特性,但是这要依赖于你所访问的java特性的实现,而且这样做远远不如在java语言中使用那些特性方便和容易。
  • native method的存在并不会对其他类调用这些本地方法产生任何影响,实际上调用这些方法的其他类甚至不知道它所调用的是一个本地方法。JVM将控制调用本地方法的所有细节。需要注意当我们将一个本地方法声明为final的情况。用java实现的方法体在被编译时可能会因为内联而产生效率上的提升。但是一个native final方法是否也能获得这样的好处却是值得怀疑的,但是这只是一个代码优化方面的问题,对功能实现没有影响。
  • 如果一个含有本地方法的类被继承,子类会继承这个本地方法并且可以用java语言重写这个方法(这个似乎看起来有些奇怪),同样的如果一个本地方法被fianl标识,它被继承后不能被重写。
  • 本地方法非常有用,因为它有效地扩充了jvm.事实上,我们所写的java代码已经用到了本地方法,在sun的java的并发(多线程)的机制实现中,许多与操作系统的接触点都用到了本地方法,这使得java程序能够超越java运行时的界限。有了本地方法,java程序可以做任何应用层次的任务。

引用: 自己动手写一个Native方法在java中调用http://www.cnblogs.com/szlbm/p/5504603.html
别人对上述链接的总结:https://www.cnblogs.com/HDK2016/p/7226840.html

1  public class TestMain
 2 {
 3     static
 4     {
 5         System.load("D:" + File.separator + "Hello.dll");
 6     }
 7     
 8     public native static void Hello();
 9     
10     public static void main(String[] args)
11     {
12         Hello();
13     }
14 }

image.png

有什么心得?

自己完成了这么一个过程,肯定是颇有成就感的,成就感过后,我们可以从这13个步骤中感悟到什么?至少个人有以下心得:

1、1个类中有很多Native方法-->这个类中的所有Native方法生成到1个.h文件中-->本地代码生成一个.dll/.so文件和一个类的Native方法实现相对应

2、为什么有Native方法的类中必有这么一段代码 ???

1 private static native void ();
2 static {
3         registerNatives();
4     }

现在想来,估计和我们的静态代码块起的作用一样,都是为这个类导入特定的.dll/.so文件用的。至于为什么不能像我们这么写,个人猜测,是因为不同的用户磁盘上的.dll/.so文件位置不固定,和JDK安装目录相关?

3、Java不在乎Native方法是用什么语言实现的,只要一来语言能和底层打 交道就好了,二来语言实现完可以提供出来.dll/.so文件。因此同一个Native方法,如果不同的Java虚拟机去调用它,那么结果可能都不同,比 如Object的hashCode(),当然,运行效率也不尽然相同,因为不同的虚拟机对于不同的Native方法有自己的实现。

2017-07-18 09:38:14 oDongFangZhiZi 阅读数 748
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57543 人正在学习 去看看 李宁

动态加载SO文件

一般编译进APK的so文件,我们可以通过以下方式去加载SO文件(注意:例如我们的so文件是libscanner.so,那么我们加载so文件的时候去掉前面的lib和后面的.so后缀

  System.loadLibrary("scanner");

有时候我们希望通过下载so后然后再动态去加载,那么可以用以下方式(注意:该方式加载so文件必须是全路径,同时由于权限的原因,必须在我们app内部存储路径,不能放在sd卡上面

System.load(f.getAbsolutePath());
2018-01-20 11:07:30 Ryan_React_Native 阅读数 833
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57543 人正在学习 去看看 李宁

React Native首屏启动白屏问题加载xml文件解决方案Android

很久没有写博客了,记录一下我前几天遇到的启动白屏加载xml文件解决办法。

一开始我在全球最大的同性交友平台github上找到了一款轻巧的解决方案,react-native-smart-splash-screen
这一个库是通过直接加载一张名为splash的固定图片作为首屏启动页面,但是现在Android手机屏幕比例五花八门,这样就会造成图片被拉伸的问题。虽然这个启动页很快就消失,但是作为一个合格的优秀的搬砖工也得学会砌墙。
首先查看了他的库,android文件夹里面有个RCTSplashScreen的Class文件,想必他是在这里面配置的,读了一下他的源码,大概意思是从我的包名资源文件下面找到一个叫spalsh文件名的图片,获取这个图片的id值,然后把这个id塞入一个ImageView对象,然后再把这个ImageView塞入一个Layout对象,最后把这个Layout放在一个dialog里面,启动的时候显示这个dialog,启动完成手动关闭这个dialog。顺着他的思路,我只需要把它的这个image换成自定义的xml文件就可以了。
是时候贴一波代码了

public class RCTSplashScreen {
    public static final int UIAnimationNone = 0;
    public static final int UIAnimationFade = 1;
    public static final int UIAnimationScale = 2;
    private static Dialog dialog;
    private static ImageView imageView;
    private static LinearLayout mLl_parent;
    private static WeakReference<Activity> wr_activity;
    protected static Activity getActivity() {
        return wr_activity.get();
    }
    public static void openSplashScreen(Activity activity) {
        openSplashScreen(activity, false);
    }
    public static void openSplashScreen(Activity activity, boolean isFullScreen) {
        openSplashScreen(activity, isFullScreen, ImageView.ScaleType.CENTER_CROP);
    }
    public static void openSplashScreen(final Activity activity, final boolean isFullScreen, final ImageView.ScaleType scaleType) {
        if (activity == null) return;
        wr_activity = new WeakReference<>(activity);
        final int drawableId = getImageId();
        if ((dialog != null && dialog.isShowing()) || (drawableId == 0)) {
            return;
        }
        activity.runOnUiThread(new Runnable() {
            public void run() {
                if (!getActivity().isFinishing()) {
                    Context context = getActivity();

                    LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);


                    View view= addView();
                    view.setLayoutParams(layoutParams);
                    dialog = new Dialog(context, isFullScreen ? android.R.style.Theme_Translucent_NoTitleBar_Fullscreen : android.R.style.Theme_Translucent_NoTitleBar);
                    dialog.setContentView(view);
                    dialog.setCancelable(false);
                    dialog.show();
                }
            }
        });
    }
    private static View addView() {
        Context context = getActivity(); // TODO 动态添加布局(xml方式)
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.splash, null);
        view.setLayoutParams(lp);
        return view;
    }
    public static void removeSplashScreen(Activity activity, final int animationType, final int duration) {
        if (activity == null) {
            activity = getActivity();
            if (activity == null) return;
        }
        activity.runOnUiThread(new Runnable() {
            public void run() {
                if (dialog != null && dialog.isShowing()) {
                    AnimationSet animationSet = new AnimationSet(true);
                    if (animationType == UIAnimationScale) {
                        AlphaAnimation fadeOut = new AlphaAnimation(1, 0);
                        fadeOut.setDuration(duration);
                        animationSet.addAnimation(fadeOut);
                        ScaleAnimation scale = new ScaleAnimation(1, 1.5f, 1, 1.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.65f);
                        scale.setDuration(duration);
                        animationSet.addAnimation(scale);
                    } else if (animationType == UIAnimationFade) {
                        AlphaAnimation fadeOut = new AlphaAnimation(1, 0);
                        fadeOut.setDuration(duration);
                        animationSet.addAnimation(fadeOut);
                    } else {
                        AlphaAnimation fadeOut = new AlphaAnimation(1, 0);
                        fadeOut.setDuration(0);
                        animationSet.addAnimation(fadeOut);
                    }
                    final View view = ((ViewGroup) dialog.getWindow().getDecorView()).getChildAt(0);
                    view.startAnimation(animationSet);
                    animationSet.setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {
                        }
                        @Override
                        public void onAnimationRepeat(Animation animation) {
                        }
                        @Override
                        public void onAnimationEnd(Animation animation) {
                            view.post(new Runnable() {
                                @Override
                                public void run() {
                                    dialog.dismiss();
                                    dialog = null;
                                    imageView = null;
                                }
                            });
                        }
                    });
                }
            }
        });
    }
    private static int getImageId() {
        int drawableId = getActivity().getResources().getIdentifier("splash", "layout", getActivity().getClass().getPackage().getName());
        if (drawableId == 0) {
            drawableId = getActivity().getResources().getIdentifier("splash", "layout", getActivity().getPackageName());
        }
        return drawableId;
    }
}

划重点:
1.getImageId()方法从当前包文件下找到名字为splash的layout文件,取到并返回它的id
2.addView()方法,实例化出来一个LayoutParams 对象,然后向里面添加xml文件,返回出来一个View对象
3.openSplashScreen()这个方法里再把这个新增的view放在dialog里面
这样就完成了~是不是不难。如果大家还有问题欢迎加我QQ交流1414770848

没有更多推荐了,返回首页