0%

简介

hook是钩子的意思,hook的过程是通过反射、代理等改变系统原有的行为以达到自己的目的。

本文主要是通过hook android 中的ActivityManagerService和Handler.CallBack,欺骗系统调起activity的过程,在调用startActivity时将targetIntent通过proxy伪装为proxyIntent,等到通过系统验证,正式启动activity时,再讲proxyIntent恢复为targetIntent,从而实现调用未在AndroidManifest.xml中注册的activity。

需要注意,本方法只在Api<26下有效。具体原因见后面。

具体实现

阅读全文 »

启动一个Service

  • MyServices.java

    必须继承自Service,或者如IntentService本身就是等其子类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class MyServices extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
    Log.d("TAG","onBind");
    return null;
    }

    @Override
    public void onCreate() {
    super.onCreate();
    Log.d("TAG","onCreate");
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    Log.d("TAG", "onDestroy: ");
    }
    }
  • AndroidManifest.xml

    注册MyServices

    1
    2
    3
    4
    5
    6
    7
    8
    <application>
    <service android:name=".MyServices"
    android:exported="true">
    <intent-filter>
    <action android:name="cf.android666.myservices" />
    </intent-filter>
    </service>
    </application>
  • MainActivity.java

    在java中调用Service,需要ServiceConnection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    Log.d(TAG, "onServiceConnected: 服务绑定");
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    Log.d(TAG, "onServiceDisconnected: 服务解绑");
    }
    };
    Intent intent = new Intent(context, MyServices.class);
    bindService(intent, mConnection, Service.BIND_AUTO_CREATE);//绑定Service
    //startService(intent); 启动service
    unbindService(mConnection);//解绑Service

    bindService()startService()的区别在于:

    ** bindService()将service和当前的activity绑定在一起,activity销毁时,service也会被销毁;

    ** startService()则只是“启动”service,在此后service的活动和activity无关,并一直存活。

Service具体分析

Service在AndroidManifest.xml中的属性:

1
2
3
4
android:name=".MyService"//必须被指定
android:exported=true/false //是否能被其他应用隐式调用
//有intent-filter则默认为true,否则默认false;若手动指定为false则即使有intent-filter也无法隐式调用
android:process="remote"/":remote"//前者在共有的进程中进行,后者在名字为{packageName}:remote 的私有进程中进行,其他进行不可访问;如果不设置该属性,则service在应用自己的进程里面运行
阅读全文 »

在之前学习android的过程中,跟着教程做了几个app,虽然随着使用的api的失效,大多数应用如今已经不能正常使用了,但是作为初入编程的一点点小纪念,还是为他们写一个索引文章,至少能够晚一些消寂于这广阔的数据海洋中。

NiceNews

Posted on 2016-05-30

NieceNews我制作的第二款APP,一个实时新闻软件。

NiceNews

阅读全文 »

这几天的工作中用到了控件组来实现复杂布局,效果不错,记录下来备用。

1. 定义控件组布局xxx_layout.xml

在这里定义要使用的控件组布局,这里的布局决定了布局显示的样子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">

<ImageView
... />

<EditText
.../>

<ImageView
... />

</LinearLayout>

2.新建自定义属性文件attr.xml(可选)

阅读全文 »

自定义的view

  • LetterIndex.java extends View
  • ContactsListView.java extends RecyclerView
    #分析
  • 联系人列表有两个要点
    • 字母导航栏
      通过自定义View画出26个字母,设置滑动监听事件,根据上下滑动的距离判断当前选中的字母,并相应更新界面。
    • 列表中的字母标题
      针对item中的联系人姓名首字母对应的tag作比较,若与前一个相同则不显示title,否则显示。
  • 事件联动
    • 当滑动字母导航栏时,除了处理本身的变化外,还要留出接口,以便其他控件获取当前选中的字母。
    • 联系人列表滑动时,除了处理本身变化外,同样要留出接口以便获取当前置顶的item对应的字母
    • 字母导航栏要留出方法,以便其他控件指定选中的字母,并更新界面

      具体代码

      ContactsListView.java
      重写该类主要是为了实现ItemDecoration根据不同的item变化,同时可以从xml布局文件中获取ItemDecoration的自定义属性。
      主要代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public ContactsListView(Context context) {
this(context, null, 0);
}

public ContactsListView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public ContactsListView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mTypeArray = context.obtainStyledAttributes(attrs, R.styleable.MyRecyclerDecoration);
mContext = context;
}

故而在其内部自定义了一个继承自ItemDecoratio得静态内部类Decorationn类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public Decoration(List<String> data){
//获取要显示的联系人数据对应的英文tag集合
//初始化各种自定义属性
//例如颜色:mColorLetterText = mTypeArray.getColor(R.styleable.MyRecyclerDecoration_color_letter_text, 0xff152648);

}

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state){
//画出各个导航title
}


@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
//画出置顶的导航title
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State
state) {
//判断是否画出导航title
super.getItemOffsets(outRect, view, parent, state);
int position = ((RecyclerView.LayoutParams) (view.getLayoutParams())).getViewAdapterPosition();

if (position != -1) {
String text = mDatas.get(position).substring(0, 1).toUpperCase();
if (position == 0) {
outRect.set(0, mTitleHeight, 0, 0);
} else if (text != null && !text.equals(mDatas.get(position - 1).substring(0, 1).toUpperCase())) {
outRect.set(0, mTitleHeight, 0, 0);
} else {
outRect.set(0, 0, 0, 0);
}
}
}

private void drawText(Canvas canvas, float left, float right, View child, String text) {
//画出文字
}
阅读全文 »

Android Studio

  • 国内较快的仓库:

    maven {url’http://maven.aliyun.com/nexus/content/groups/public/'}

  • RecyclerView添加依赖
    注意RecyclerView的版本号要和当前工程中其他android.support包版本保持一致,否则虽然导入了对应的包,但是仍然无法正常使用。

    compile ‘com.android.support:recyclerview-v7:26+’

  • 设置:
    自动添加依赖:insert imports on paste: None
    自动删除无用依赖:Optimize imports on the fly

Linux

  • 设置ndk环境变量 /etc/profile

    #set ndk env
    NDKROOT=/home/jixiaoyong/AndroidDev/Sdk/ndk-bundle
    export PATH=$NDKROOT:$PATH

今天重新学习类三种排序方法,按照排序速度依次是冒泡排序,选择排序和插入排序。
以下示例皆为从小到大的排序

1.冒泡排序

每一次比较都可能要交换元素。
冒泡排序的思想是:
每一轮开始的时候,将第一个元素(a)开始与其后的元素(b)依次进行比较,将较大的元素(设为m)放到后面,并将m与其后的另外一个元素继续进行比较,直到最后一个没有排好序的元素。
在接下来一轮的排序中,刚才以及之前选出来的、已经排好顺序的最大值不用参与排序。
依次类推,总共遍历n-1轮,即可完成排序。
具体代码如下:

 void bubble(int[] arr){
    int temp;
    for (int i = 0; i < arr.length - 1; i++) {
        for (int j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    
    System.out.println("\n--bubble :");
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i] + " ");
    }
}

2.选择排序

阅读全文 »

下载 JDK 并解压

  • 到官网下载 jdk
  • 下载到的 JDK 文件解压

设置环境变量

管理员权限进入 etc/environment 写入以下代码

1
JAVA_HOME="JDK主目录的绝对路径"
阅读全文 »

这几天学习 AppWidget ,很简单的组件却花费了不少功夫,今天对 PendingIntent 的用法做了一些简单的整理。

PendingIntent

PandingIntent 就像是一个设计好的处理预案,当达到某个特定条件时,便会调用该 Intent 所指定动作(打开服务,Activity或者发送广播)。

这里使用该方法在 AppWidget 里面为按钮添加监听事件,当按钮被点击的时候触发相应的动作

AppWidget 和应用程序不再同一个进程当中,而是在 HomeScreen 上面执行,所以不能直接为 AppWidget 中的 Button 添加监听事件,需要用 remoteViews.setPendingIntent(R.id.widget_button,pendingIntent);意思是当按下按钮的时候 pendingIntent 中的 Intent 就会执行

PendingIntent 当某个事件出现之后才会执行

阅读全文 »