• Android是一种特权分隔的操作系统,在Android上运行的每个应用程序都具有各自独立的系统标识(Linux用户ID和组ID)。系统各部分有不同的身份标识。因此,Linux上运行的各个应用程序相互独立且与系统无关。  ...

        Android是一种特权分隔的操作系统,在Android上运行的每个应用程序都具有各自独立的系统标识(Linux用户ID和组ID)。系统各部分有不同的身份标识。因此,Linux上运行的各个应用程序相互独立且与系统无关。


        Android的“权限许可”机制通过限定特定的进程能够执行的指定操作和限定对每一个资源点对点的访问的URI许可来提供附加细粒度的安全功能。


        由于内核让每个应用程序运行在独立的沙盒中,应用程序必须通过声明所需要而沙盒没有提供的权限来明确的分配资源和数据。Android没有采用会使用户体验复杂并且不利于安全的动态授权机制。应用程序静态的声明他们所需要的权限,在程序安装时Android系统会提示用户同意它们获取这些权限。


       Android权限模型是基于如下两个目标而设计的:
    通知用户:

        通过列出应用程序可能执行的所有敏感的操作,让用户更多地意识到安装这个应用存在的潜在风险。这假定用户会阅读在安装时弹出的权限列表,并基于这些信息来作出是否安装应用的决定。
    降低风险:
        通过限制应用程序访问Android系统敏感的API接口,来降低应用程序对整个系统带来的伤害(比如病毒)。


       Android权限被分为四个等级:
    普通级:

        这些权限并不能真正伤害到用户(比如更换壁纸),当程序需要这些权限是,开发者不需要指定程序会自动赋予这些权限。
    危险级:

        这些权限可能会带来真的伤害(比如打电话,打开网络链接等),如果要使用它们需要开发者在AndroidManifest.xml中声明对应的权限。
    签名级:

        如果应用使用的是相同的签名证书时,这些权限会自动授予给声明或者创建这些权限的程序。设计这一层级权限的目的是方便组件间数据共享。
    签名/系统级:

        和签名级一样,例外的是系统镜像是自动获取这些权限的,这一层级是专为设备制造商设计的。


        在开发Android应用程序的过程中,如果我们要使用系统的某些服务(比如网络、待机、读写文件权限等)都需要首先像下面这样在AndroidManifest.xml中声明对应的权限,然后才可以在代码中访问这些服务:

    <!-- 文件读写权限 -->
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    
        <!-- 访问网络的权限 -->
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
        <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
        
        <!-- 屏幕唤醒权限 -->
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <uses-permission android:name="android.permission.DEVICE_POWER" />
        同样,除了能够使用Android系统提供的各种权限外,我们还可以自定义权限来限制其它程序访问应用的各种服务或者组件。任何程序想要和此程序的组件交互时,都需要声明相应的权限时才能成功地访问。


    自定义权限步骤如下:

        以为一个服务CalledService定义访问权限为例,具体步骤如下:

    1、在被调用程序Called的AndroidManifest.xml文件中作如下定义:

    <!-- Service Permission -->
        <permission
            android:name="com.uperone.permission.SERVICE"
            android:label="@string/app_name"
            android:permissionGroup="@string/app_name"
            android:protectionLevel="normal" >
        </permission>

    关于各标签属性的意义自行脑补,都是见名知意。

    <service
                android:name="com.uperone.called.service.CalledService"
                android:permission="com.uperone.permission.SERVICE">
                <intent-filter>
                    <action android:name="com.uperone.action.SERVICE" />
                    <category android:name="android.intent.category.DEFAULT"/>
                </intent-filter>
            </service>

    2、在需要调用该组件的应用程序Call工程的AndroidManifest.mxl文件中声明对应的权限:

    <uses-permission android:name="com.uperone.permission.SERVICE" />

    3、在需要调用该组件的应用程序Call工程中启动、停止改服务:

    case R.id.startServiceBtnId:{
    			Intent intent = new Intent( "com.uperone.action.SERVICE" );
    			startService(intent);
    		}
    		break;
    特别注意:如果在调用需要权限的组件时没有在Manifest.xml中声明权限,则会在运行对应代码段时报异常!!!!

    更多组件自定义权限参见实例:Android自定义权限permission


    展开全文
  • Android 自定义View (一)

    2016-08-10 19:19:53
    很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章。先总结下自定义View的步骤: 1、自定义View的属性 2、...

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901

    很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章。先总结下自定义View的步骤:

    1、自定义View的属性

    2、在View的构造方法中获得我们自定义的属性

    [ 3、重写onMesure ]

    4、重写onDraw

    我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的。

    1、自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <attr name="titleText" format="string" />
        <attr name="titleTextColor" format="color" />
        <attr name="titleTextSize" format="dimension" />
    
        <declare-styleable name="CustomTitleView">
            <attr name="titleText" />
            <attr name="titleTextColor" />
            <attr name="titleTextSize" />
        </declare-styleable>
    
    </resources>
    我们定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:

    一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;不清楚的可以google一把。

    然后在布局中声明我们的自定义View

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <com.example.customview01.view.CustomTitleView
            android:layout_width="200dp"
            android:layout_height="100dp"
            custom:titleText="3712"
            custom:titleTextColor="#ff0000"
            custom:titleTextSize="40sp" />
    
    </RelativeLayout>

    一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我们的命名空间,后面的包路径指的是项目的package

    2、在View的构造方法中,获得我们的自定义的样式

    /**
    	 * 文本
    	 */
    	private String mTitleText;
    	/**
    	 * 文本的颜色
    	 */
    	private int mTitleTextColor;
    	/**
    	 * 文本的大小
    	 */
    	private int mTitleTextSize;
    
    	/**
    	 * 绘制时控制文本绘制的范围
    	 */
    	private Rect mBound;
    	private Paint mPaint;
    
    	public CustomTitleView(Context context, AttributeSet attrs)
    	{
    		this(context, attrs, 0);
    	}
    
    	public CustomTitleView(Context context)
    	{
    		this(context, null);
    	}
    
    	/**
    	 * 获得我自定义的样式属性
    	 * 
    	 * @param context
    	 * @param attrs
    	 * @param defStyle
    	 */
    	public CustomTitleView(Context context, AttributeSet attrs, int defStyle)
    	{
    		super(context, attrs, defStyle);
    		/**
    		 * 获得我们所定义的自定义样式属性
    		 */
    		TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);
    		int n = a.getIndexCount();
    		for (int i = 0; i < n; i++)
    		{
    			int attr = a.getIndex(i);
    			switch (attr)
    			{
    			case R.styleable.CustomTitleView_titleText:
    				mTitleText = a.getString(attr);
    				break;
    			case R.styleable.CustomTitleView_titleTextColor:
    				// 默认颜色设置为黑色
    				mTitleTextColor = a.getColor(attr, Color.BLACK);
    				break;
    			case R.styleable.CustomTitleView_titleTextSize:
    				// 默认设置为16sp,TypeValue也可以把sp转化为px
    				mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
    						TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
    				break;
    
    			}
    
    		}
    		a.recycle();
    
    		/**
    		 * 获得绘制文本的宽和高
    		 */
    		mPaint = new Paint();
    		mPaint.setTextSize(mTitleTextSize);
    		// mPaint.setColor(mTitleTextColor);
    		mBound = new Rect();
    		mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
    
    	}

    我们重写了3个构造方法,默认的布局文件调用的是两个参数的构造方法,所以记得让所有的构造调用我们的三个参数的构造,我们在三个参数的构造中获得自定义属性。

    3、我们重写onDraw,onMesure调用系统提供的:

    @Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    	{
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    	}
    
    	@Override
    	protected void onDraw(Canvas canvas)
    	{
    		mPaint.setColor(Color.YELLOW);
    		canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
    
    		mPaint.setColor(mTitleTextColor);
    		canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
    	}
    此时的效果是:

    是不是觉得还不错,基本已经实现了自定义View。但是此时如果我们把布局文件的宽和高写成wrap_content,会发现效果并不是我们的预期:


    系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。

    所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:

    重写之前先了解MeasureSpec的specMode,一共三种类型:

    EXACTLY:一般是设置了明确的值或者是MATCH_PARENT

    AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT

    UNSPECIFIED:表示子布局想要多大就多大,很少使用

    下面是我们重写onMeasure代码:

    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    	{
    		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    		int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    		int width;
    		int height ;
    		if (widthMode == MeasureSpec.EXACTLY)
    		{
    			width = widthSize;
    		} else
    		{
    			mPaint.setTextSize(mTitleTextSize);
    			mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);
    			float textWidth = mBounds.width();
    			int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());
    			width = desired;
    		}
    
    		if (heightMode == MeasureSpec.EXACTLY)
    		{
    			height = heightSize;
    		} else
    		{
    			mPaint.setTextSize(mTitleTextSize);
    			mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);
    			float textHeight = mBounds.height();
    			int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());
    			height = desired;
    		}
    		
    		
    
    		setMeasuredDimension(width, height);
    	}
    

    现在我们修改下布局文件:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <com.example.customview01.view.CustomTitleView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            custom:titleText="3712"
            android:padding="10dp"
            custom:titleTextColor="#ff0000"
            android:layout_centerInParent="true"
            custom:titleTextSize="40sp" />
    
    </RelativeLayout>

    现在的效果是:


    完全复合我们的预期,现在我们可以对高度、宽度进行随便的设置了,基本可以满足我们的需求。

    当然了,这样下来我们这个自定义View与TextView相比岂不是没什么优势,所有我们觉得给自定义View添加一个事件:

    在构造中添加:

    this.setOnClickListener(new OnClickListener()
    		{
    
    			@Override
    			public void onClick(View v)
    			{
    				mTitleText = randomText();
    				postInvalidate();
    			}
    
    		});

    private String randomText()
    	{
    		Random random = new Random();
    		Set<Integer> set = new HashSet<Integer>();
    		while (set.size() < 4)
    		{
    			int randomInt = random.nextInt(10);
    			set.add(randomInt);
    		}
    		StringBuffer sb = new StringBuffer();
    		for (Integer i : set)
    		{
    			sb.append("" + i);
    		}
    
    		return sb.toString();
    	}

    下面再来运行:


    我们添加了一个点击事件,每次让它随机生成一个4位的随机数,有兴趣的可以在onDraw中添加一点噪点,然后改写为验证码,是不是感觉很不错。


    好了,各位学习的,打酱油的留个言,顶个呗~


    源码点击此处下载






    展开全文
  • 对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现: 自定义一个CustomView(extends View )类 编写values/attrs.xml,在其中编写styleable和item等标签元素 在布局文件中CustomView使用自定义的属性...

    转载请标明出处:
    http://blog.csdn.net/lmj623565791/article/details/45022631
    本文出自:【张鸿洋的博客】

    1、引言

    对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现:

    1. 自定义一个CustomView(extends View )类
    2. 编写values/attrs.xml,在其中编写styleable和item等标签元素
    3. 在布局文件中CustomView使用自定义的属性(注意namespace)
    4. 在CustomView的构造方法中通过TypedArray获取

    ps:如果你对上述几个步骤不熟悉,建议先熟悉下,再继续~

    那么,我有几个问题:

    • 以上步骤是如何奏效的?
    • styleable 的含义是什么?可以不写嘛?我自定义属性,我声明属性就好了,为什么一定要写个styleable呢?
    • 如果系统中已经有了语义比较明确的属性,我可以直接使用嘛?
    • 构造方法中的有个参数叫做AttributeSet
      (eg: MyTextView(Context context, AttributeSet attrs) )这个参数看名字就知道包含的是参数的数组,那么我能不能通过它去获取我的自定义属性呢?
    • TypedArray是什么鬼?从哪冒出来的,就要我去使用?

    恩,针对这几个问题,大家可以考虑下,如何回答呢?还是说:老子会背上述4个步骤就够了~~

    2、常见的例子

    接下来通过例子来回答上述问题,问题的回答顺序不定~~大家先看一个常见的例子,即上述几个步骤的代码化。

    • 自定义属性的声明文件
        <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <declare-styleable name="test">
            <attr name="text" format="string" />
            <attr name="testAttr" format="integer" />
        </declare-styleable>
    
    </resources>
    • 自定义View类
    package com.example.test;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    
    public class MyTextView extends View {
    
        private static final String TAG = MyTextView.class.getSimpleName();
    
        public MyTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.test);
    
            String text = ta.getString(R.styleable.test_testAttr);
            int textAttr = ta.getInteger(R.styleable.test_text, -1);
    
            Log.e(TAG, "text = " + text + " , textAttr = " + textAttr);
    
            ta.recycle();
        }
    
    }
    • 布局文件中使用
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:zhy="http://schemas.android.com/apk/res/com.example.test"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <com.example.test.MyTextView
            android:layout_width="100dp"
            android:layout_height="200dp"
            zhy:testAttr="520"
            zhy:text="helloworld" />
    
    </RelativeLayout>

    ok,大家花3s扫一下,运行结果为:

     MyTextView: text = helloworld , textAttr = 520

    应该都不意外吧,注意下,我的styleable的name写的是test,所以说这里并不要求一定是自定义View的名字。

    3、AttributeSet与TypedArray

    下面考虑:

    构造方法中的有个参数叫做AttributeSet(eg: MyTextView(Context context, AttributeSet attrs) )这个参数看名字就知道包含的是参数的集合,那么我能不能通过它去获取我的自定义属性呢?

    首先AttributeSet中的确保存的是该View声明的所有的属性,并且外面的确可以通过它去获取(自定义的)属性,怎么做呢?
    其实看下AttributeSet的方法就明白了,下面看代码。

    public MyTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            int count = attrs.getAttributeCount();
            for (int i = 0; i < count; i++) {
                String attrName = attrs.getAttributeName(i);
                String attrVal = attrs.getAttributeValue(i);
                Log.e(TAG, "attrName = " + attrName + " , attrVal = " + attrVal);
            }
    
            // ==>use typedarray ...
    
        }
    

    输出:

    MyTextView(4136): attrName = layout_width , attrVal = 100.0dip
    MyTextView(4136): attrName = layout_height , attrVal = 200.0dip
    MyTextView(4136): attrName = text , attrVal = helloworld
    MyTextView(4136): attrName = testAttr , attrVal = 520
    

    结合上面的布局文件,你发现了什么?
    我擦,果然很神奇,真的获得所有的属性,恩,没错,通过AttributeSet可以获得布局文件中定义的所有属性的key和value(还有一些方法,自己去尝试),那么是不是说TypedArray这个鬼可以抛弃了呢?答案是:NO!

    现在关注下一个问题:

    TypedArray是什么鬼?从哪冒出来的,就要我去使用?

    我们简单修改下,布局文件中的MyTextView的属性。

    <com.example.test.MyTextView
            android:layout_width="@dimen/dp100"
            android:layout_height="@dimen/dp200"
            zhy:testAttr="520"
            zhy:text="@string/hello_world" />

    现在再次运行的结果是:

    MyTextView(4692): attrName = layout_width , attrVal = @2131165234
    MyTextView(4692): attrName = layout_height , attrVal = @2131165235
    MyTextView(4692): attrName = text , attrVal = @2131361809
    MyTextView(4692): attrName = testAttr , attrVal = 520
    >>use typedarray
    MyTextView(4692): text = Hello world! , textAttr = 520

    发现了什么?通过AttributeSet获取的值,如果是引用都变成了@+数字的字符串。你说,这玩意你能看懂么?那么你看看最后一行使用TypedArray获取的值,是不是瞬间明白了什么。

    TypedArray其实是用来简化我们的工作的,比如上例,如果布局中的属性的值是引用类型(比如:@dimen/dp100),如果使用AttributeSet去获得最终的像素值,那么需要第一步拿到id,第二步再去解析id。而TypedArray正是帮我们简化了这个过程。

    贴一下:如果通过AttributeSet获取最终的像素值的过程:

    int widthDimensionId =  attrs.getAttributeResourceValue(0, -1);
            Log.e(TAG, "layout_width= "+getResources().getDimension(widthDimensionId));
    

    ok,现在别人问你TypedArray存在的意义,你就可以告诉他了。

    4、declare-styleable

    我们已经解决了两个问题,接下来,我们看看布局文件,我们有一个属性叫做:zhy:text
    总所周知,系统提供了一个属性叫做:android:text,那么我觉得直接使用android:text更nice,这样的话,考虑问题:

    如果系统中已经有了语义比较明确的属性,我可以直接使用嘛?

    答案是可以的,怎么做呢?
    直接在attrs.xml中使用android:text属性。

        <declare-styleable name="test">
            <attr name="android:text" />
            <attr name="testAttr" format="integer" />
        </declare-styleable>

    注意,这里我们是使用已经定义好的属性,不需要去添加format属性(注意声明和使用的区别,差别就是有没有format)。
    然后在类中这么获取:ta.getString(R.styleable.test_android_text);布局文件中直接android:text="@string/hello_world"即可。

    这里提一下,系统中定义的属性,其实和我们自定义属性的方式类似,你可以在sdk/platforms/android-xx/data/res/values该目录下看到系统中定义的属性。然后你可以在系统提供的View(eg:TextView)的构造方法中发现TypedArray获取属性的代码(自己去看一下)。

    ok,接下来,我在想,既然declare-styleable这个标签的name都能随便写,这么随意的话,那么考虑问题:

    styleable 的含义是什么?可以不写嘛?我自定义属性,我声明属性就好了,为什么一定要写个styleable呢?

    其实的确是可以不写的,怎么做呢?

    • 首先删除declare-styleable的标签

    那么现在的attrs.xml为:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <attr name="testAttr" format="integer" />
    </resources>

    哟西,so清爽~
    * MyTextView实现

    package com.example.test;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    
    public class MyTextView extends View {
    
        private static final String TAG = MyTextView.class.getSimpleName();
    
        private static final int[] mAttr = { android.R.attr.text, R.attr.testAttr };
        private static final int ATTR_ANDROID_TEXT = 0;
        private static final int ATTR_TESTATTR = 1;
    
        public MyTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            // ==>use typedarray
            TypedArray ta = context.obtainStyledAttributes(attrs, mAttr);
    
            String text = ta.getString(ATTR_ANDROID_TEXT);
            int textAttr = ta.getInteger(ATTR_TESTATTR, -1);
            //输出 text = Hello world! , textAttr = 520
            Log.e(TAG, "text = " + text + " , textAttr = " + textAttr);
    
            ta.recycle();
        }
    
    }
    

    貌似多了些代码,可以看到我们声明了一个int数组,数组中的元素就是我们想要获取的attr的id。并且我们根据元素的在数组中的位置,定义了一些整形的常量代表其下标,然后通过TypedArray进行获取。
    可以看到,我们原本的:

    R.styleable.test => mAttr
    R.styleable.test_text => ATTR_ANDROID_TEXT(0)
    R.styleable.test_testAttr => ATTR_TESTATTR(1)

    那么其实呢?android在其内部也会这么做,按照传统的写法,它会在R.java生成如下代码:

    public static final class attr {
        public static final int testAttr=0x7f0100a9;
        }
    public static final class styleable {
         public static final int test_android_text = 0;
         public static final int test_testAttr = 1;
          public static final int[] test = {
                0x0101014f, 0x7f0100a9
            };
        }

    ok,根据上述你应该发现了什么。styleale的出现系统可以为我们完成很多常量(int[]数组,下标常量)等的编写,简化我们的开发工作(想想如果一堆属性,自己编写常量,你得写成什么样的代码)。那么大家肯定还知道declare-styleable的name属性,一般情况下写的都是我们自定义View的类名。主要为了直观的表达,该declare-styleable的属性,都是改View所用的。

    其实了解该原理是有用的,详见:Android 自定义控件 优雅实现元素间的分割线

    ok,现在5个问题,回答了4个,第一个问题:

    自定义属性的几个步骤是如何奏效的?

    恩,上述以及基本涵盖了这个问题的答案,大家自己总结,所以:略。

    总结下今天的博客。

    • attrs.xml里面的declare-styleable以及item,android会根据其在R.java中生成一些常量方便我们使用(aapt干的),本质上,我们可以不声明declare-styleable仅仅声明所需的属性即可。
    • 我们在View的构造方法中,可以通过AttributeSet去获得自定义属性的值,但是比较麻烦,而TypedArray可以很方便的便于我们去获取。
    • 我们在自定义View的时候,可以使用系统已经定义的属性。

    近期的更新计划:自定义View的一些细节相关的Blog(重点会在交互上),Android最佳实践相关的文章,framework相关的一些文章,敬请期待。

    群号:423372824

    微信公众号:hongyangAndroid
    (欢迎关注,第一时间推送博文信息)

    展开全文
  • Android-自定义PopupWindow

    2014-05-12 21:55:19
    Android-自定义PopupWindow2014年5月12日 PopupWindow在应用中应该是随处可见的,很常用到,比如在旧版本的微信当中就用到下拉的PopupWindow,那是自定义的。新版微信5.2的ActionBar,有人已经模仿了它,但微信具体...
    Android-自定义PopupWindow

    2014年5月12日
    PopupWindow在应用中应该是随处可见的,很常用到,比如在旧版本的微信当中就用到下拉的PopupWindow,那是自定义的。新版微信5.2的ActionBar,有人已经模仿了它,但微信具体是使用了ActionBar还是其他的笔者倒是不太清楚,本篇博客主要介绍如何自定义一个PopupWindow来供自己在开发应用时使用。因为笔者最近在开发一款应用时用到这个知识点,所以自己实现了类似新版微信的效果。
    效果图如下:




    首先从布局开始
    /14_CustomPopupWindow/res/layout/activity_swipe.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/animation_layout_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:orientation="vertical" >
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/abc_ab_bottom_solid_dark_holo"
            android:padding="12dip" >
    
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:gravity="center"
                android:orientation="horizontal" >
    
                <ImageView
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:src="@drawable/ic_launcher" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dip"
                    android:text="任务系统"
                    android:textColor="@color/lightgray"
                    android:textSize="18sp" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:gravity="center"
                android:orientation="horizontal" >
    
                <Button
                    android:id="@+id/btnSearch"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_marginRight="20dip"
                    android:background="@drawable/actionbar_search_icon"
                    android:visibility="gone" />
    
                <Button
                    android:id="@+id/btnAdd"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_marginRight="20dip"
                    android:background="@drawable/actionbar_add_icon" />
    
                <Button
                    android:id="@+id/btnSet"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:background="@drawable/actionbar_more_icon" />
            </LinearLayout>
        </RelativeLayout>
    
    
    </LinearLayout>

    /14_CustomPopupWindow/res/layout/add_popup_dialog.xml
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical" >
    
        <LinearLayout
            android:id="@+id/pop_layout2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:background="@drawable/abc_ab_bottom_solid_dark_holo"
            android:gravity="center_horizontal"
            android:orientation="vertical" >
    
            <LinearLayout
                android:id="@+id/add_task_layout"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp" >
    
                <ImageView
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:scaleType="fitCenter"
                    android:src="@drawable/ofm_add_icon" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="10dp"
                    android:gravity="center"
                    android:text="添加任务"
                    android:textColor="@color/white"
                    android:textSize="15dip" />
            </LinearLayout>
    
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="0.2dp"
                android:background="@color/black" />
    
            <LinearLayout
                android:id="@+id/team_member_layout"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp" >
    
                <ImageView
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:scaleType="fitCenter"
                    android:src="@drawable/ofm_profile_icon" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="10dp"
                    android:gravity="center"
                    android:text="团队成员"
                    android:textColor="@color/white"
                    android:textSize="15dip" />
            </LinearLayout>
    
        </LinearLayout>
    
    </RelativeLayout>



    /14_CustomPopupWindow/res/layout/more_popup_dialog.xml
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical" >
    
        <LinearLayout
            android:id="@+id/pop_layout"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:background="@drawable/abc_ab_bottom_solid_dark_holo"
            android:gravity="center_horizontal"
            android:orientation="vertical" >
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp" >
    
                <ImageView
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:src="@drawable/defalt_head" />
    
                <LinearLayout
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:gravity="left|center_horizontal"
                    android:orientation="vertical"
                    android:padding="5dp" >
    
                    <TextView
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:text="wwj"
                        android:textColor="@color/white"
                        android:textSize="15sp" />
    
                    <TextView
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:text="whatswwj"
                        android:textColor="@color/green"
                        android:textSize="15sp" />
                </LinearLayout>
            </LinearLayout>
    
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="0.2dp"
                android:background="@color/black" />
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp" >
    
                <ImageView
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:scaleType="fitCenter"
                    android:src="@drawable/ofm_photo_icon" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="10dp"
                    android:gravity="center"
                    android:text="我的相册"
                    android:textColor="@color/white"
                    android:textSize="15sp" />
            </LinearLayout>
    
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="0.2dp"
                android:background="@color/black" />
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp"
                android:visibility="gone" >
    
                <ImageView
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:scaleType="fitCenter"
                    android:src="@drawable/ofm_collect_icon" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="10dp"
                    android:gravity="center"
                    android:text="我的收藏"
                    android:textColor="@color/white"
                    android:textSize="15sp" />
            </LinearLayout>
    
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="0.2dp"
                android:background="@color/black" />
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp"
                android:visibility="gone" >
    
                <ImageView
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:scaleType="fitCenter"
                    android:src="@drawable/ofm_card_icon" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="10dp"
                    android:gravity="center"
                    android:text="我的银行卡"
                    android:textColor="@color/white"
                    android:textSize="15sp" />
            </LinearLayout>
    
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="0.2dp"
                android:background="@color/black"
                android:visibility="gone" />
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp" >
    
                <ImageView
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:scaleType="fitCenter"
                    android:src="@drawable/ofm_setting_icon" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="10dp"
                    android:gravity="center"
                    android:text="设置"
                    android:textColor="@color/white"
                    android:textSize="15sp" />
            </LinearLayout>
    
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="0.2dp"
                android:background="@color/black" />
    
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:padding="8dp" >
    
                <ImageView
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:scaleType="fitCenter"
                    android:src="@drawable/ofm_blacklist_icon" />
    
                <Button
                    android:id="@+id/btn_cancel"
                    android:layout_width="wrap_content"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="10dp"
                    android:background="@null"
                    android:gravity="center"
                    android:text="退出登录"
                    android:textColor="@color/white"
                    android:textSize="15sp" />
            </LinearLayout>
        </LinearLayout>
    
    </RelativeLayout>

    以上分别是主页面和两个popupWindow布局

    下面自定义两个PopupWindow,自己封装自己想要的PopuoWindow,这里只是给出示例


    /14_CustomPopupWindow/src/com/wwj/popupwindow/AddPopWindow.java
    package com.wwj.popupwindow;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.drawable.ColorDrawable;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.LinearLayout;
    import android.widget.PopupWindow;
    
    /**
     * 自定义popupWindow
     * 
     * @author wwj
     * 
     * 
     */
    public class AddPopWindow extends PopupWindow {
    	private View conentView;
    
    	public AddPopWindow(final Activity context) {
    		LayoutInflater inflater = (LayoutInflater) context
    				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    		conentView = inflater.inflate(R.layout.add_popup_dialog, null);
    		int h = context.getWindowManager().getDefaultDisplay().getHeight();
    		int w = context.getWindowManager().getDefaultDisplay().getWidth();
    		// 设置SelectPicPopupWindow的View
    		this.setContentView(conentView);
    		// 设置SelectPicPopupWindow弹出窗体的宽
    		this.setWidth(w / 2 + 50);
    		// 设置SelectPicPopupWindow弹出窗体的高
    		this.setHeight(LayoutParams.WRAP_CONTENT);
    		// 设置SelectPicPopupWindow弹出窗体可点击
    		this.setFocusable(true);
    		this.setOutsideTouchable(true);
    		// 刷新状态
    		this.update();
    		// 实例化一个ColorDrawable颜色为半透明
    		ColorDrawable dw = new ColorDrawable(0000000000);
    		// 点back键和其他地方使其消失,设置了这个才能触发OnDismisslistener ,设置其他控件变化等操作
    		this.setBackgroundDrawable(dw);
    		// mPopupWindow.setAnimationStyle(android.R.style.Animation_Dialog);
    		// 设置SelectPicPopupWindow弹出窗体动画效果
    		this.setAnimationStyle(R.style.AnimationPreview);
    		LinearLayout addTaskLayout = (LinearLayout) conentView
    				.findViewById(R.id.add_task_layout);
    		LinearLayout teamMemberLayout = (LinearLayout) conentView
    				.findViewById(R.id.team_member_layout);
    		addTaskLayout.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View arg0) {
    				AddPopWindow.this.dismiss();
    			}
    		});
    
    		teamMemberLayout.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				AddPopWindow.this.dismiss();
    			}
    		});
    	}
    
    	/**
    	 * 显示popupWindow
    	 * 
    	 * @param parent
    	 */
    	public void showPopupWindow(View parent) {
    		if (!this.isShowing()) {
    			// 以下拉方式显示popupwindow
    			this.showAsDropDown(parent, parent.getLayoutParams().width / 2, 18);
    		} else {
    			this.dismiss();
    		}
    	}
    }
    


    /14_CustomPopupWindow/src/com/wwj/popupwindow/MorePopWindow.java
    package com.wwj.popupwindow;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.drawable.ColorDrawable;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.PopupWindow;
    
    public class MorePopWindow extends PopupWindow {
    	private View conentView;
    
    	public MorePopWindow(final Activity context) {
    		LayoutInflater inflater = (LayoutInflater) context
    				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    		conentView = inflater.inflate(R.layout.more_popup_dialog, null);
    		int h = context.getWindowManager().getDefaultDisplay().getHeight();
    		int w = context.getWindowManager().getDefaultDisplay().getWidth();
    		// 设置SelectPicPopupWindow的View
    		this.setContentView(conentView);
    		// 设置SelectPicPopupWindow弹出窗体的宽
    		this.setWidth(w / 2 + 50);
    		// 设置SelectPicPopupWindow弹出窗体的高
    		this.setHeight(LayoutParams.WRAP_CONTENT);
    		// 设置SelectPicPopupWindow弹出窗体可点击
    		this.setFocusable(true);
    		this.setOutsideTouchable(true);
    		// 刷新状态
    		this.update();
    		// 实例化一个ColorDrawable颜色为半透明
    		ColorDrawable dw = new ColorDrawable(0000000000);
    		// 点back键和其他地方使其消失,设置了这个才能触发OnDismisslistener ,设置其他控件变化等操作
    		this.setBackgroundDrawable(dw);
    		// mPopupWindow.setAnimationStyle(android.R.style.Animation_Dialog);
    		// 设置SelectPicPopupWindow弹出窗体动画效果
    		this.setAnimationStyle(R.style.AnimationPreview);
    
    	}
    
    	public void showPopupWindow(View parent) {
    		if (!this.isShowing()) {
    			this.showAsDropDown(parent, parent.getLayoutParams().width / 2, 18);
    		} else {
    			this.dismiss();
    		}
    	}
    }
    


    上面用到一个动画样式效果:
    /14_CustomPopupWindow/res/values/styles.xml
     <style name="AnimationPreview">
            <item name="android:windowEnterAnimation">@anim/fade_in</item>
            <item name="android:windowExitAnimation">@anim/fade_out</item>
        </style>

    用到两个动画资源
    /14_CustomPopupWindow/res/anim/fade_in.xml
    <?xml version="1.0" encoding="utf-8"?>
    <!-- 左上角扩大-->
      <scale   xmlns:android="http://schemas.android.com/apk/res/android"
            android:interpolator="@android:anim/accelerate_decelerate_interpolator"  
            android:fromXScale="0.001" 
            android:toXScale="1.0"   
            android:fromYScale="0.001"   
            android:toYScale="1.0"   
            android:pivotX="100%"  
            android:pivotY="10%"  
            android:duration="200" />  
       

    /14_CustomPopupWindow/res/anim/fade_out.xml
    <?xml version="1.0" encoding="utf-8"?>
    <!-- 左上角缩小 -->
      <scale   xmlns:android="http://schemas.android.com/apk/res/android"
            android:interpolator="@android:anim/accelerate_decelerate_interpolator"  
            android:fromXScale="1.0"   
            android:toXScale="0.001"   
            android:fromYScale="1.0"   
            android:toYScale="0.001"   
            android:pivotX="100%"  
            android:pivotY="10%" 
            android:duration="200" />  
       






    /14_CustomPopupWindow/src/com/wwj/popupwindow/MainActivity.java
    package com.wwj.popupwindow;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    
    public class MainActivity extends Activity implements OnClickListener{
    	private Button setButton;
    	private Button addButton;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_swipe);
    		
    		setButton = (Button) findViewById(R.id.btnSet);
    		addButton = (Button) findViewById(R.id.btnAdd);
    		setButton.setOnClickListener(this);
    		addButton.setOnClickListener(this);;
    	}
    	
    	@Override
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case R.id.btnSet:
    			MorePopWindow morePopWindow = new MorePopWindow(MainActivity.this);
    			morePopWindow.showPopupWindow(setButton);
    			break;
    		case R.id.btnSearch:
    			
    			break;
    		case R.id.btnAdd:
    			AddPopWindow addPopWindow = new AddPopWindow(MainActivity.this);
    			addPopWindow.showPopupWindow(addButton);
    			break;
    		default:
    			break;
    		}
    	}
    }
    

    以上是代码实现,具体可以下载源码参考。






    展开全文
  • Android源码添加自定义系统服务 本文以一个简单的例子详细介绍如何为Android 6.0 系统新增一个系统服务,以及如何使用自定义系统服务。 目标:1.创建一个自定义服务CCCService 2.APP 开发过程中可以使用 ...

    Android源码添加自定义系统服务

    本文以一个简单的例子详细介绍如何为Android 6.0 系统新增一个系统服务,以及如何使用自定义系统服务。

    目标:1.创建一个自定义服务CCCService

            2.APP 开发过程中可以使用 getSystemService("ccc") 获取 CCCManager 并且调用里面的函数。

     step1 创建aidl文件

    在源码frameworks/base/core/java/android/os/ 下面新增 一个 ICCCService.aidl

    假设我们定义了5个函数,这些函数将会在SystemServer进程执行。

    内容如下 

    // ICCCService.aidl
    package android.os;
    
    // Declare any non-default types here with import statements
    
    interface ICCCService {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
       void setVal(String key,String value);
       String getVal(String key);
       void appendLog(String log);
       void clearLog();
       String readLog();
    }
    

    step2 创建Service文件 (CCCService)

    在 frameworks/base/services/core/java/com/android/server/ 下面新增一个 CCCService.java 用来实现aidl文件定义的接口。

    内容如下

    package com.android.server;
    
    import java.io.InputStreamReader;
    import java.io.LineNumberReader;
    import java.lang.*;
    import java.util.HashMap;
    import android.os.RemoteException;
    import android.os.ICCCService;
    
    
    /**
     *
     * Created by zhuangqianliu on 2016/9/21.
     */
    
    public class CCCService extends ICCCService.Stub {
        private static HashMap<String,String> map=new HashMap<>();
        private static String inner_log="";
    
        public CCCService() {
    
        }
    
        @Override
        public void setVal(String key, String value) throws RemoteException {
            map.put(key,value);
        }
    
        @Override
        public String getVal(String key) throws RemoteException {
            return map.get(key);
        }
    
        @Override
        public void appendLog(String log) throws RemoteException {
            inner_log+=log+"\n";
        }
    
        @Override
        public void clearLog() throws RemoteException {
            inner_log="";
        }
    
        @Override
        public String readLog() throws RemoteException {
            return inner_log;
        }
    
    }
    

    step3 将自定义Service 加入到SystemServer 启动进程

    先在 frameworks/base/core/java/android/content/Context.java 中添加一行 

    public static final String CCC_SERVICE="ccc";

    修改 frameworks/base/services/java/com/android/server/SystemServer.java

    在  startOtherServices() 函数 的try模块中增加以下代码

     try {
    
                    Slog.i(TAG, "CCC Service");
    
                    ServiceManager.addService(Context.CCC_SERVICE, new CCCService());
    
                } catch (Throwable e) {
    
                    Slog.e(TAG, "Failure starting CCC Service", e);
    
                }

    最终效果如图

     

    step4 创建Manager,即CCCManager

    在frameworks/base/core/java/android/app/ 下创建CCCManager.java 文件 内容如下

    package android.app;
    
    /**
     * Created by liam on 16/10/2.
     */
    import android.annotation.SdkConstant;
    import android.annotation.SystemApi;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Build;
    import android.os.Parcel;
    import android.os.Parcelable;
    import android.os.RemoteException;
    import android.os.ICCCService;
    import android.util.Log;
    
    public class CCCManager {
        ICCCService mService;
        public CCCManager(Context ctx,ICCCService service){
            mService=service;
        }
        public void setVal(String key,String value){
            try{
                mService.setVal(key,value);
            }catch(Exception e){
                Log.e("CCCManager",e.toString());
                e.printStackTrace();
            }
    
        }
        public String getVal(String key){
            try{
                return mService.getVal(key);
            }catch(Exception e){
                Log.e("CCCManager",e.toString());
                e.printStackTrace();
            }
            return null;
        }
        public void appendLog(String log){
            try{
                mService.appendLog(log);
            }catch(Exception e){
                Log.e("CCCManager",e.toString());
                e.printStackTrace();
            }
        }
        public void clearLog(){
            try{
                mService.clearLog();
            }catch(Exception e){
                Log.e("CCCManager",e.toString());
                e.printStackTrace();
            }
        }
        public String readLog(){
            try{
                return mService.readLog();
            }catch(Exception e){
                Log.e("CCCManager",e.toString());
                e.printStackTrace();
            }
            return null;
        }
    }
    

    step5 注册到SystemService

    修改frameworks/base/core/java/android/app/SystemServiceRegistry.java

    在静态代码块中增加

     registerService(Context.CCC_SERVICE, CCCManager.class,
                    new CachedServiceFetcher<CCCManager>() {
                        @Override
                        public CCCManager createService(ContextImpl ctx) {
                            IBinder b = ServiceManager.getService(Context.CCC_SERVICE);
                            ICCCService service = ICCCService.Stub.asInterface(b);
                            return new CCCManager(ctx, service);
                        }});
    

    step6 修改SePolicy的编译验证

    修改 /external/sepolicy/service.te

    在最后一行添加

    type ccc_service, system_api_service, system_server_service, service_manager_type;

    然后修改同目录下 /external/sepolicy/service_contexts 文件

    中间插入一行 

    ccc u:object_r:ccc_service:s0

    如图所示

     

    step7 重新编译源码

    别忘了先 make update-api。

    Step8 测试 

     

    tip: 

    可以先创建一个java工程简单写一个CCCManager类,导出jar 在ide中使用provided 依赖。这样开发过程中就不会报错。

    java临时工程如下使用 IDEA创建的java项目

     

    Android studio 项目配置

     

     

    展开全文
  • 前言:在我从C++转到Android时,就被Android里炫彩斑斓的自定义控件深深折服,想知道如果想利用C++实现这些功能,那是相当困难的。从那时候起,我就想,等我学会了自定义控件,一定要写一篇系列出来,方便后来者能更...
  • 需求,希望在Android ROM中添加相应的LogService服务,保存每次的log,用于处理系统死机问题; 本文档基于rk的5.1.1系统; 基本框架: 5.1.1系统在framework/base/services/java/...
  • 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38339817 , 本文出自:【张鸿洋的博客】...说白了,就是教大家如何自定义ViewGroup,如果你对自定义ViewGroup还不是很了解,或者正想学习如何自
  • Android系统对话框——自定义关闭Dialog是我们在项目中经常用到的,5.x以后的Dialog也很好看,很安卓风,Android也给我们提供了新的包,低版本可以显示一样的效果。我们在使用的导入v7包下的Dialog即可。样式不是...
  • Android发送自定义广播

    2019-01-21 14:23:54
    Android系统不仅存在系统级广播,用户也可以自定义广播。Android系统中的广播可以分为两种类型:1.标准广播 2.有序广播。 1.标准广播  标准广播完全异步执行,在广播发出之后,所有的广播接收器几乎可以同时接收...
  • Android中实现分享有一种比较方便的方式,调用系统的分享面板来分享我们的应用。最基本的实现如下: public Intent getShareIntent(){ Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); ...
  • android自定义软键盘

    2018-05-18 14:48:44
    本篇文章将会介绍3种android自定义软键盘的应用场景以及代码编写,分别是:普通的自定义软键盘;每次弹出都会改变数字顺序的自定义密码键盘;能与webview交互的自定义密码键盘。以上说的这三种其实本质上没有太大...
  • android软件设计中会用到好多的控件,但系统自带的控件有好多不能够达到需要实现的功能或是控件不够美观。那怎么办呢? android应为我们提供了好多的控件,我们可以继承某一控件,然后对它进行重写来实现自己的...
  • 在目录路径为 android\frameworks\base\core\java\android\kt\debuginfo 添加文件: IDebugInfoProviderManager.aidl 这里添加你所需要实现的两个抽象接口。 2、注册aidl到编译脚本Android.mk文件中 在目录...
  • Android中,相信都在自己的程序中调用过系统相机拍照或者选择图片,但直接调用系统相机有时候并不能满足我们的需求,或者说我们如何去自定义一个相机,那么,我们可以通过Camera和SurfaceView来实现自己的相机应用...
  • Android自定义组件 android自定义组件一般有三种实现方式: 一、组合控件:组合控件,顾名思义就是将一些小的控件组合起来形成一个新的控件,这些小的控件多是系统自带的控件。 二、自绘控件: 何为自绘控件,就是...
  • res/drawable/tab_indicator.xml res/color/tab_indicator_text.xml res/layout/tab_indicator.xml <RelativeLayout xmlns:android="http://schemas.android.
  • 系统自带的SeekBar真是太难看了,不能容忍! 只能自己做了,先来张效果图 第1个Seekbar 背景是颜色,thumb是图片,上代码: <SeekBar android:id="@+id/timeline" android:layout_width="fill_parent" ...
  • 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回顾一下,我们一共学习了...现在前半部分的承诺已经如约兑现了,那么今天我就要来兑现后面部分的承诺,讲一讲自定义View的实现方法,同时这也是带
  • 前言 「知足常乐」,很多人不满足现状,各种折腾,往往舍本逐末,常乐才能少一分浮躁,多一分宁静。近期在小编身上发生了许多事情,心态也发生了很大的改变,有感于现实的无奈...但每次都因为系统自带的LinearLayou...
1 2 3 4 5 ... 20
收藏数 170,844
精华内容 68,337