AndroidStudio配置NDK环境

1、新建工程,在工程根目录找到local.properties文件

sdk.dir=C\:/Languages/Android/android-sdk-windows
ndk.dir=C\:/Languages/Android/android-ndk-r10

2、在app\build.gradle文件中的defaultConfig段内增加

       ndk {
            moduleName "yourModuleName"
       }

2、在工程的app\src\main目录下,新增jni文件夹,将你的ndk工程拷进去

3、在app\src\main\java目录下,将你的java文件拷贝进去

4、如果你的ndk工程用到了其他so文件,在app目录下,新建jniLibs文件夹,将so文件拷贝进去

jniLibs\armeabi\xxx.so
jniLibs\armeabi-v7a\xxx.so
....

5、自定义文件夹路径。编辑app\build.gradle文件下的android段

    //自定义引用库路径
    sourceSets.main {
        jniLibs.srcDir 'src/main/cpplibs'
    }

    //自定义源码路径
    sourceSets.main {
        jni.srcDirs 'src/main/cpp'
    }

6、现在就可以用啦

7、另一种方式就是,先把so文件用命令行生成好,然后,android项目中直接引用so文件就好了

PS:
如果你的ndk项目只有一个c文件,用早期的AndroidStudio编译会报错:

make.exe: *** No rule to make target
......

Execution failed for task ':XXXXXX:compileXXXXXXDebugNdk'.
.......

这样的话,在你的c文件目录下,随便建立一个空的c文件,重新编译就好了,好挫。

Android配置NDK环境

准备工作
1、下载NDK
2、直接运行,会解压到当前文件夹
3、剪切到你喜欢的文件夹

第一个项目
1、写一个调用JNI的Java类

package com.neohope.android.jni;

public class JniFunc {
    private native int  addNative(int a, int b);

    static {
        System.loadLibrary("jnifunc");
    }

    public int add(int a, int b)
    {
        return addNative(a,b);
    }
}

2、用你喜欢的方式,编译为class文件

3、用jdk的javah工具生成头文件

#在class文件的顶层路径,比如这个例子,就在com这个文件夹相同目录下
javah com.neohope.android.jni.JniFunc

会输出文件“com_neohope_android_jni_JniFunc.h”:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_neohope_android_jni_JniFunc */

#ifndef _Included_com_neohope_android_jni_JniFunc
#define _Included_com_neohope_android_jni_JniFunc
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_neohope_android_jni_JniFunc
 * Method:    addNative
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_neohope_android_jni_JniFunc_addNative
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

4、编写“com_neohope_android_jni_JniFunc.c”

#include <jni.h>
#include "com_neohope_android_jni_JniFunc.h"

JNIEXPORT jint JNICALL Java_com_neohope_android_jni_JniFunc_addNative
  (JNIEnv *evn, jobject obj, jint a, jint b)
{
    return a+b;
}

5、编写Android.mk及Application.mk

APP_ABI := all
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := jnifunc
LOCAL_SRC_FILES := com_neohope_android_jni_JniFunc.c \

LOCAL_C_INCLUDES += com_neohope_android_jni_JniFunc.h

include $(BUILD_SHARED_LIBRARY)

6、编译

SET NDK_HOME="C:\Languages\Android\android-ndk-r10d"

SET PATH=%NDK_HOME%;%PATH%

CMD

REM ndk-build

Andoid百度地图显示方向

    private BaiduMap mBaiduMap = null;
    private MapView mMapView = null;
    private LocationClient mLocClient = null;
    private MyLocationConfiguration.LocationMode mCurrentMode;
    private Boolean isFirstLoc = true;
    private BitmapDescriptor mCurrentMarker=null;

    private float[] accelerometerValues=new float[3];
    private float[] magneticFieldValues=new float[3];
    private float[] values=new float[3];
    private float[] rotate=new float[9];
    private float[] degree=new float[3];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_main);

        SensorManager sm = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
        SensorEventListener sensorEventListener = new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
                    accelerometerValues=event.values;
                }
                if(event.sensor.getType()==Sensor.TYPE_MAGNETIC_FIELD){
                    magneticFieldValues=event.values;
                }
                else
                {
                    return;
                }

                SensorManager.getRotationMatrix(rotate, null, accelerometerValues, magneticFieldValues);
                SensorManager.getOrientation(rotate, values);

                //rotate
                degree[0] = values[0]/3.1415926f*180;
                //up down
                degree[1] = values[1]/3.1415926f*180;
                //left right
                degree[2] = values[2]/3.1415926f*180;
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
            }
        };

        sm.registerListener(sensorEventListener,sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
        sm.registerListener(sensorEventListener,sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_NORMAL);

        // init baiduMap
        mMapView = (MapView) findViewById(R.id.dbmapView);
        mBaiduMap = mMapView.getMap();

        // set parameters
        mCurrentMode = MyLocationConfiguration.LocationMode.FOLLOWING;
        mCurrentMarker=null;
        mBaiduMap.setMyLocationConfigeration(new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker));

        // allow loaction
        mBaiduMap.setMyLocationEnabled(true);
        mLocClient = new LocationClient(this);
        mLocClient.registerLocationListener(new MyLocationListenner());
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true);
        option.setCoorType("bd09ll");
        option.setScanSpan(1000);
        mLocClient.setLocOption(option);
        mLocClient.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMapView.onDestroy();
    }

    public class MyLocationListenner implements BDLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            if (location == null || mMapView == null)
                return;

            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    .direction(degree[0])
                    .latitude(location.getLatitude())
                    .longitude(location.getLongitude()).build();
            mBaiduMap.setMyLocationData(locData);

            if (isFirstLoc) {
                isFirstLoc = false;
                LatLng ll = new LatLng(location.getLatitude(),
                        location.getLongitude());
                MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
                mBaiduMap.animateMapStatus(u);
            }
        }
    }

Android读取并解析Json

1、不可以在UI线程直接读取网络数据,所以另起线程处理这件事情

public class MainActivity extends ActionBarActivity implements IParseJsonCallback,IParseHtmlCallback{

    public void ParseJsonPage(List<PhaseResultBean> resultList) {
        new ParseJson(this).execute(resultList);
    }

    @Override
    public void ParseJsonDone(List<PhaseResultBean> resultList) {
        //回调函数
    }
}

2、回调接口

package com.neohope.android.gpjj;

import java.util.List;

public interface IParseJsonCallback {
        void ParseJsonDone(List<PhaseResultBean> resultList);
}

3、解析Json类

package com.neohope.android.gpjj;

import android.os.AsyncTask;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class ParseJson extends AsyncTask<String,Void,List<PhaseResultBean>>{

    private IParseJsonCallback jsonCallback;

    public ParseJson(IParseJsonCallback jsonCallback)
    {
        this.jsonCallback = jsonCallback;
    }

    @Override
    protected List<PhaseResultBean> doInBackground(String... params) {
        if(params==null)return null;
        List<PhaseResultBean> resultList= new ArrayList<PhaseResultBean>();

        String jsonString = params[0];
        try {
            JSONObject json= new JSONObject(jsonString);
            JSONArray jijinlist = json.getJSONArray("jijinlist");

            for(int i=0;i<jijinlist.length();i++)
            {
                JSONObject JJ= jijinlist.getJSONObject(i);
                PhaseResultBean result = new PhaseResultBean();
                result.code = JJ.getString("code");
                resultList.add(result);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return resultList;
    }

    @Override
    protected void onPostExecute(List<PhaseResultBean> resultList) {
        super.onPostExecute(resultList);
        jsonCallback.ParseJsonDone(resultList);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
}

Android用JSoup解析网页

1、不可以在UI线程直接读取网络数据,所以另起线程处理这件事情

public class MainActivity extends ActionBarActivity implements IParseJsonCallback,IParseHtmlCallback{

    public void ParseHtmlPage(List<PhaseResultBean> resultList) {
        new ParseHtml(this).execute(resultList);
    }

    @Override
    public void ParseHtmlDone(List<PhaseResultBean> resultList) {
        //回调函数
    }
}

2、回调接口

package com.neohope.android.gpjj;

import java.util.List;

public interface IParseHtmlCallback {
    void ParseHtmlDone(List<PhaseResultBean> resultList);
}

3、解析HTML类

package com.neohope.android.gpjj;

import android.os.AsyncTask;
import android.util.Log;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.List;

public class ParseHtml extends AsyncTask<List<PhaseResultBean>,Void,List<PhaseResultBean>>{

    private IParseHtmlCallback htmlCallback;

    public ParseHtml(IParseHtmlCallback htmlCallback)
    {
        this.htmlCallback = htmlCallback;
    }

    @Override
    protected List<PhaseResultBean> doInBackground(List<PhaseResultBean>... paramList) {
        if(paramList==null)return null;
        List<PhaseResultBean> params = paramList[0];
        for(PhaseResultBean bean : params) {
            Document doc = null;
            String url = bean.httpUrl;
            try {
                doc = Jsoup.connect(url).userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6").timeout(5000).followRedirects(true).get();
            } catch (IOException ex) {
                Log.w("", ex.getMessage());
                return null;
            }

            Document content = Jsoup.parse(doc.toString());
            Element dodydiv = content.getElementById("bodydiv");
            Element div = dodydiv.child(6).child(1).child(0).child(0);

            Element code = div.child(0).child(2);
            String szCode = code.text();

            Element title = div.child(0).child(1);
            String szTitle = title.text();

            bean.code = szCode;
            bean.name = szTitle;
        }

        return params;
    }

    @Override
    protected void onPostExecute(List<PhaseResultBean> listResult) {
        super.onPostExecute(listResult);
        htmlCallback.ParseHtmlDone(listResult);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
}

Android任务栏通知

        private static int nId = 0;

        private void RaiseSysTrayAlert(List<NEventBean> eventList)
        {
            NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            Context context = getApplicationContext();

            for(NEventBean bean : eventList)
            {
                Builder mBuilder = new Builder(context);
                mBuilder.setTicker("XXXX");
                mBuilder.setSmallIcon(R.drawable.ic_launcher);
                mBuilder.setContentTitle("XXXX");
                mBuilder.setContentText(bean.msg);
                mBuilder.setAutoCancel(true);

                Intent notifyIntent = new Intent(context, MainActivity.class);
                notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                PendingIntent pIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                mBuilder.setContentIntent(pIntent);

                nId++;
                nm.notify(nId, mBuilder.build());
            }
        }

Android后台服务及自动运行

1、修改AndroidManifest.xml文件

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

<application ...>
        <service
            android:name="com.neohope.android.service.NService"
            android:enabled="true"
            android:exported="true" >
        </service>

        <receiver android:name="com.neohope.android.receiver.NBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
</application>

2、新增服务类

package com.neohope.android.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;

public class NService extends Service {

    public NService() {
        
    }

    @Override
    public void onCreate() {
        mainThread = new WorkThread ();
        mainThread.start();
    }

    @Override
    public void onDestroy() {
        mainThread.bEnd = true;
    }

    class WorkThread extends Thread
    {
        private int nInterval = 1000*60;
        private boolean bEnd = false;

        public JsonReaderThread()
        {
        }

        @Override
        public void run()
        {
            while(!bEnd)
            {
                DoSomething();

                try {
                    Thread.sleep(nInterval);
                } catch (InterruptedException e) {
                    Log.w("", "");
                }
            }
        }

        private void DoSomething()
        {
        }

}

3、新增广播处理类

package com.neohope.android.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.neohope.android.service.NService;

public class NBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent startServiceIntent = new Intent(context, NService.class);
        context.startService(startServiceIntent);
    }
}

4、在Activity中添加启动代码

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        doStartService();
    }

    public void doStartService() {
        Context context = getApplicationContext();
        Intent startServiceIntent = new Intent(context, NService.class);
        context.startService(startServiceIntent);
    }

Android读取网页内容

1、修改AndroidManifest.xml文件

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

2、网页读取类

package com.neohope.android.web;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

public class HttpUtils {

    public static String readStringFromUrl(String szUrl,String szCharcode) throws IOException {
        URL url = new URL(szUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5 * 1000);
        conn.setRequestMethod("GET");

        String szJson = "";
        int resPonseCode = conn.getResponseCode();
        if (conn.getResponseCode() == 200)
        {
            InputStream is = conn.getInputStream();
            byte[] data = readStream(is);
            szJson = new String(data,szCharcode);
        }

        return szJson;
    }

    private static byte[] readStream(InputStream inputStream) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            bout.write(buffer, 0, len);
        }
        bout.close();
        inputStream.close();

        return bout.toByteArray();
    }
}

AndroidStudio打包so文件

AndroidStudio打包so文件方法如下:
1、将so文件,用下面的文件结构打包为一个zip包,并修改后缀为jar,如armeabi.jar
/lib/armeabi/*.so

2、将armeabi.jar拷贝到项目的libs文件夹下
/your_project/app/libs

3、AndroidStudio会默认将libs下的*.jar一起打包

这样就好啦

从WIN ADT复制到MAC ADT

Android SDK超级大(我现在有26.5G),而连接Google的速度超级慢,一次下载要好久。

最近准备在MAC进行Android开发,别的都好下载,但Adroid SDK就有些太大了,于是考虑从WIN下直接复制到MAC。

Android SDK主要由下面几部分组成:

/add-ons:GoogleAPI,操作系统无关
/build-tools:构建工具,这个和操作系统相关的,要重新下载
/docs:文档,操作系统无关
/extras:扩展内容,是否需要重新下载与其功能有关
/extras/android:操作系统无关
/extras/google:操作系统无关
/extras/intel:intel的硬件加速驱动,操作系统相关,需重新下载
/platforms:android平台,早期操作系统相关,后期将操作系统相关内容放到了build-tools中,可以全部拷贝过去,系统相关内容会自动重新下载
/platform-tools:管理工具,这个和操作系统相关的,要重新下载
/samples:demo,操作系统无关
/sources:android源码,操作系统无关
/system-images:android系统映像,操作系统无关
/temp:下载缓存,不需要拷贝
/tools:管理工具,这个和操作系统相关的,要重新下载