[置顶] *知识点积累————温故而知新


友情提示根据目录 快速查找问题

%1$s %1$d Android string
1、整型,比如“我今年23岁了”,这个23是整型的。在string.xml中可以这样写,<string name="old">我今年%1$d岁了</string> 
在程序中,使用 
[java] view plaincopy
  1. String sAgeFormat = getResources().getString(R.string.old);  
  2. String sFinalAge = String.format(sAgeFormat, 23);  
将%1$d替换为23; 

%1$d表达的意思是整个name=”old”中,第一个整型的替代。如果一个name中有两个需要替换的整型内容,则第二个写为:%2$d,以此类推;具体程序中替换见下面的string型; 

2、string型,比如“我的名字叫李四,我来自首都北京”;这里的“李四”和“首都北京”都需要替换。 
在string.xml中可以这样写,<string name="alert">我的名字叫%1$s,我来自%2$s</string> 
在程序中: 
[java] view plaincopy
  1. view sourceprint?1 String sAgeFormatString sAgeFormat1= getResources().getString(R.string.alert);     
  2.   
  3. String sFinal1 = String.format(sAgeFormat1, "李四","首都北京");   
这里两个string需要替换的,按照上面程序的顺序依次对应。

<xliff:g>标签介绍: 
属性id可以随便命名 
属性值举例说明
%n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空格 
%n$md:代表输出的是整数,n代表是第几个参数,设置m的值可以在输出之前放置空格,也可以设为0m,在输出之前放置m个0 
%n$mf:代表输出的是浮点数,n代表是第几个参数,设置m的值可以控制小数位数,如m=2.2时,输出格式为00.00 

也可简单写成:

%d   (表示整数)

%f    (表示浮点数)

%s   (表示字符串)

使用步骤举例:

1.

<?xml version="1.0" encoding="utf-8"?>

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 

2.

 <string name="test_xliff">小红今年<xliff:g id="xxx">%d</xliff:g>岁了,上<xliff:g id="yyy">%s</xliff:g>年级!</string>

3. 

String test = String.format(getResources().getString(R.string.test_xliff), 7, "小学二");

输出:

小红今年7岁了,上小学二年级!

浏览器中  %3A  代表 :   %2F 代表 /

http %3A %2F%2F images.%2F82005team-dcppg01shandianxiawulaibang.jpg

http://images/XXX.jpg

两个 安卓 原生的控件  效果也挺好看的

原生控件  swiperefreshlayout   和 progressbar

效果也不错

[置顶] *知识点积累————温故而知新_第1张图片

布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

 <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

    <ListView 
          android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        
    </ListView>
    </android.support.v4.widget.SwipeRefreshLayout>
  <ProgressBar
        android:id="@+id/progressbar"
        style="@android:style/Widget.ProgressBar"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_centerInParent="true"
        android:indeterminate="false"
        android:indeterminateDrawable="@drawable/loading"
        android:padding="5dp"
        android:visibility="invisible" />
</RelativeLayout>

loading.xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="1080.0" >

    <shape
        android:innerRadiusRatio="3"
        android:shape="ring"
        android:thicknessRatio="18"
        android:useLevel="false" >
        <gradient
            android:centerColor="#FFDC35"
            android:centerY="0.50"
            android:endColor="#14CCB2"
            android:startColor="#FFFFFF"
            android:type="sweep"
            android:useLevel="false" />
    </shape>

</rotate>

代码:

public class MainActivity extends Activity implements OnRefreshListener {

	private SwipeRefreshLayout swipe;
	private ProgressBar mProgressBar;

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

		mProgressBar = (ProgressBar) findViewById(R.id.progressbar);
		
		swipe = (SwipeRefreshLayout) findViewById(R.id.swipe);
		swipe.setOnRefreshListener(this);
		// 顶部刷新的样式
		swipe.setColorSchemeResources(android.R.color.holo_red_light,
				android.R.color.holo_green_light,
				android.R.color.holo_blue_bright,
				android.R.color.holo_orange_light);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void onRefresh() {
		mProgressBar.setVisibility(View.VISIBLE);
		Timer timer = new Timer();
		TimerTask task = new TimerTask() {

			@Override
			public void run() {
				runOnUiThread(new Runnable() {
					
					@Override
					public void run() {
						swipe.setRefreshing(false);
						mProgressBar.setVisibility(View.INVISIBLE);
					}
				});
				
			}
		};
		timer.schedule(task, 3000);
	}

}

浸入状态栏 

[置顶] *知识点积累————温故而知新_第2张图片

在 SetcontentView 前面 添加 两行代码,从 sdk  19 以后 才有的效果
@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //透明状态栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //透明导航栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
		setContentView(R.layout.activity_main);
		
		LinearLayout ll=new LinearLayout(this);		
	}

代码中设置  TextView  的 drawableleft   ,图片 与文字 之间的 间距问题


		findViewById.setText("神");
		findViewById.setGravity(Gravity.CENTER_VERTICAL);
		//在左侧添加图片
		Drawable drawable= getResources().getDrawable(R.drawable.ic_launcher);
		drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
		
		findViewById.setCompoundDrawables(drawable, null, null, null);
//		textView.setTextColor(getResources().getColor(R.color.gray_textcolor_shen));
		findViewById.setCompoundDrawablePadding(400);//设置图片和text之间的间距 
		findViewById.setPadding(-5, 0, 0, 0);

 在同一进程的 两个activity  之间传递 bitmap 

	Intent intent=new Intent();
	intent.putExtra("Bitmap", saveBitmap);
	Bitmap bitmap = getIntent().getParcelableExtra("Bitmap");

保存bitmap 到本地

/**
 * 保存bitmap 到本地	
 * @param path  : 绝对路径
 * @param bitmap:bitmap 
 */
public static void saveBitmap(String path,Bitmap bitmap)

{
	  File f = new File(path + System.currentTimeMillis() + ".png");
	  try {
	   f.createNewFile();
	  } catch (IOException e) {
	 
	   LogUtils.d("在保存图片时出错:"+e.toString());
	  }
	  FileOutputStream fOut = null;
	  try {
	   fOut = new FileOutputStream(f);
	  } catch (FileNotFoundException e) {
	   e.printStackTrace();
	  }
	  bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
	  try {
	   fOut.flush();
	  } catch (IOException e) {
	   e.printStackTrace();
	  }
	  try {
	   fOut.close();
	  } catch (IOException e) {
	   e.printStackTrace();
	  }
}

-----------------------------------------------------------------------------------------------------------------------
[置顶] *知识点积累————温故而知新_第3张图片




代码设置 样式 

     // 文字
            TextView appNameText=new TextView(UIUtils.getContext());
            appNameText.setTextAppearance(UIUtils.getContext(), R.style.ChannelTextStyle);
            appNameText.setText(appInfo.title);


如何让Android下的多行EditText焦点光标默认在第一行 .

只要加上android:gravity="top"就搞定OK了。

在Android开发中如何移除EditText上的输入焦点 ?

当我们创建一个带EditText 或 AutoCompleteTextView的视图时,在加载视图时总是会把输入的焦点自动移动到第一个输入框。如何改成最终效果呢?且看本文详解。
当我们创建一个带EditText 或 AutoCompleteTextView的视图时,在加载视图时总是会把输入的焦点自动移动到第一个输入框。如下图所示:

[置顶] *知识点积累————温故而知新_第4张图片

下面是mail.xml布局文件

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <button
        android:id="@+id/Button01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_text" >
    </button>

    <edittext
        android:id="@+id/EditText01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/hint"
        android:text="" >
    </edittext>

    <button
        android:id="@+id/Button02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_text" >
    </button>

</linearlayout>


我们如何才能把焦点从EditText上移除呢?最简单的方法是创建一个不可见的(invisible)LinearLayout,LinearLayout将会把焦点从EditText上移走。

我们修改mail.xml布局文件,在EditText之前增加一个LinearLayout ,如下所示:

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <button
        android:id="@+id/Button01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_text" >
    </button>

    <linearlayout
        android:layout_width="0px"
        android:layout_height="0px"
        android:focusable="true"
        android:focusableintouchmode="true" >

        <edittext
            android:id="@+id/EditText01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="@string/hint"
            android:text="" >
        </edittext>

        <button
            android:id="@+id/Button02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/button_text" >
        </button>
    </linearlayout>

</linearlayout>

最终效果如下所示:

[置顶] *知识点积累————温故而知新_第5张图片

不需要任何代码就把焦点移除了,是不是最简单的解决方案?

Android 禁止软键盘自动弹出

Android系统对EditText这个控件有监听功能,如果某个Activity中含有该控件,就会自动弹出软键盘让你输入,这个看似人性化的方案有时候并不被用户喜欢的,所以在有些情况下要禁用该功能。这几天做的应用也有这个问题,所以就查了,网上大部分都是如下方法:

[html]  view plain copy
  1. <activity android:name=".MainActivity"  
  2.                android:screenOrientation="landscape"  
  3.                android:windowSoftInputMode="adjustPan|stateHidden"  
  4.                android:configChanges="orientation|keyboardHidden">           
  5.                <intent-filter>  
  6.                    <action android:name="android.intent.action.MAIN"/>  
  7.                    <category android:name="android.intent.category.LAUNCHER"/>  
  8.                </intent-filter>         
  9.      </activity>   

该方法确实有用,但只是在刚进入此Activity时能起到左右,如果该Activity中有Tab功能的切换,软键盘又会弹出来,所以有了下面这个解决办法:

在xml文件中加入一个隐藏的TextView:

[html]  view plain copy
  1. <TextView  
  2.         android:id="@+id/config_hidden"  
  3.         android:layout_width="wrap_content"  
  4.         android:layout_height="wrap_content"  
  5.         android:focusable="true"  
  6.         android:focusableInTouchMode="true"  
  7.         />  

然后再在Activity中加入:

[java]  view plain copy
  1. TextView config_hidden = (TextView) this.findViewById(R.id.config_hidden);  
[java]  view plain copy
  1. config_hidden.requestFocus();  

这样软键盘就不会弹出了。


Android锁屏状态下弹出activity,如新版qq的锁屏消息提示

在接收消息广播的onReceive里,跳转到你要显示的界面。如:
  1. Intent intent = new Intent(arg0,MainActivity.class);
  2. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        
  3. arg0.startActivity(intent);
在该activity的onCreate()方法里:
  1. super.onCreate(savedInstanceState);
  2. getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED|WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
  3. setContentView(R.layout.activity_main);

设置activity的theme属性:
  1. android:theme="@android:style/Theme.Wallpaper.NoTitleBar"
添加点击事件,进入app,突破锁屏:
  1. KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
  2. KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("");
  3. keyguardLock.disableKeyguard();
在menifest中加入该权限:
  1. <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
这样就可以啦,在此保存,以备后用。感兴趣的小伙伴们快去试试吧!

java通过生日得到星座

private final static int[] dayArr = new int[] { 20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22 };  
private final static String[] constellationArr = new String[] { "摩羯座", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座" };  
  
  
public static String getConstellation(int month, int day) {  
    return day < dayArr[month - 1] ? constellationArr[month - 1] : constellationArr[month];  
}  

onItemLongClick长点击事件

  1.      gridview.setOnItemLongClickListener(new OnItemLongClickListener() {  
  2.   
  3.         @Override  
  4.         public boolean onItemLongClick(AdapterView<?> arg0, View arg1,  
  5.                 int arg2, long arg3) {  
  6.             // TODO Auto-generated method stub  
  7.             Log.e("setOnItemLongClickListener""setOnItemLongClickListener");  
  8.             return true;  
  9.         }  
  10.            
  11.   
  12.       });  
  13.      gridview.setOnItemClickListener(new OnItemClickListener(){  
  14.   
  15. @Override  
  16. public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,  
  17.         long arg3) {  
  18.     Log.e("setOnItemClickListener""setOnItemClickListener");  
  19. }  
  20.           
  21.      });  

 

在处理长按时,注意的细节是把onItemLongClick返回设置为true,否则长按是会执行setOnItemClickListener。


Android中如何获取视频文件的缩略图

在android中获取视频文件的缩略图有三种方法:

1.从媒体库中查询

2. android 2.2以后使用ThumbnailUtils类获取

3.调用jni文件,实现MediaMetadataRetriever类

三种方法各有利弊

第一种方法,新视频增加后需要SDCard重新扫描才能给新增加的文件添加缩略图,灵活性差,而且不是很稳定,适合简单应用

第二种方法,实现简单,但2.2以前的版本不支持

第三种方法,实现复杂,但比较灵活,推荐使用

下面给出三种方法的Demo

1.第一种方法:

public static Bitmap getVideoThumbnail(ContentResolver cr, String fileName) {
Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
//select condition.
String whereClause = MediaStore.Video.Media.DATA + ” = ‘”
+ fileName + “‘”;
Log.v(TAG, “where = ” + whereClause);
//colection of results.
Cursor cursor = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Video.Media._ID }, whereClause,
null, null);
Log.v(TAG, “cursor = ” + cursor);
if (cursor == null || cursor.getCount() == 0) {
return null;
}
cursor.moveToFirst();
//image id in image table.
String videoId = cursor.getString(cursor
.getColumnIndex(MediaStore.Video.Media._ID));
Log.v(TAG, “videoId = ” + videoId);
if (videoId == null) {
return null;
}
cursor.close();
long videoIdLong = Long.parseLong(videoId);
//via imageid get the bimap type thumbnail in thumbnail table.
bitmap = MediaStore.Video.Thumbnails.getThumbnail(cr, videoIdLong,
Images.Thumbnails.MICRO_KIND, options);
Log.v(TAG, “bitmap = ” + bitmap);
return bitmap;
}

2. 第二种方法:

通过ThumbnailUtils的三种静态方法。

1. static Bitmap createVideoThumbnail(String filePath, int kind) //获取视频文件的缩略图,第一个参数为视频文件的位置,比如/sdcard/android123.3gp,而第二个参数可以为MINI_KIND或 MICRO_KIND最终和分辨率有关
2. static Bitmap extractThumbnail(Bitmap source, int width, int height, int options) //直接对Bitmap进行缩略操作,最后一个参数定义为OPTIONS_RECYCLE_INPUT ,来回收资源
3. static Bitmap extractThumbnail(Bitmap source, int width, int height) // 这个和上面的方法一样,无options选项

3. 第三种方法:

MediaMetadataRetriever是android中隐藏的一个类,开发者无法调用,只能实现一个相同的类来完成相关功能。

一种方式是修改android源码,将frameworks  MediaMetadataRetriever.java中@hide标签去掉,在current.xml中添加MediaMetadataRetriever到可用.重新编译frameworks,应用就可以调用到MediaMetadataRetriever这个类了…这样是不适合应用开发的。

推荐的方法是实现MediaMetadataRetriever类

第一步:首先需要下载JNI库:libmedia_jni.so

进入SDK的Tools目录下,运行DDMS,
在DDMS中的菜单栏中,执行Device–FileExplore,
在弹出的文件列表中选择: System-Lib-libmedia_jni.so
选中这个文件后, 在弹出的文件列表的又上脚执行PULL file from device,提取出libmedia_jni.so文件
在Eclipse中新建文件夹libs-armeabi-,在里面放入libmedia_jni.so文件

第二部:实现MediaMetadataRetriever

public class MediaMetadataRetriever
{
static {
System.loadLibrary(“media_jni”);
native_init();
}
// The field below is accessed by native methods
@SuppressWarnings(“unused”)
private int mNativeContext;
public MediaMetadataRetriever() {
native_setup();
}
/**
* Call this method before setDataSource() so that the mode becomes
* effective for subsequent operations. This method can be called only once
* at the beginning if the intended mode of operation for a
* MediaMetadataRetriever object remains the same for its whole lifetime,
* and thus it is unnecessary to call this method each time setDataSource()
* is called. If this is not never called (which is allowed), by default the
* intended mode of operation is to both capture frame and retrieve meta
* data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY).
* Often, this may not be what one wants, since doing this has negative
* performance impact on execution time of a call to setDataSource(), since
* both types of operations may be time consuming.
*
* @param mode The intended mode of operation. Can be any combination of
* MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY:
* 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY:
*    For neither frame capture nor meta data retrieval
* 2. MODE_GET_METADATA_ONLY: For meta data retrieval only
* 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only
* 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY:
*    For both frame capture and meta data retrieval
*/
public native void setMode(int mode);
/**
* @return the current mode of operation. A negative return value indicates
* some runtime error has occurred.
*/
public native int getMode();
/**
* Sets the data source (file pathname) to use. Call this
* method before the rest of the methods in this class. This method may be
* time-consuming.
*
* @param path The path of the input media file.
* @throws IllegalArgumentException If the path is invalid.
*/
public native void setDataSource(String path) throws IllegalArgumentException;
/**
* Sets the data source (FileDescriptor) to use.  It is the caller’s
* responsibility to close the file descriptor. It is safe to do so as soon
* as this call returns. Call this method before the rest of the methods in
* this class. This method may be time-consuming.
*
* @param fd the FileDescriptor for the file you want to play
* @param offset the offset into the file where the data to be played starts,
* in bytes. It must be non-negative
* @param length the length in bytes of the data to be played. It must be
* non-negative.
* @throws IllegalArgumentException if the arguments are invalid
*/
public native void setDataSource(FileDescriptor fd, long offset, long length)
throws IllegalArgumentException;
/**
* Sets the data source (FileDescriptor) to use. It is the caller’s
* responsibility to close the file descriptor. It is safe to do so as soon
* as this call returns. Call this method before the rest of the methods in
* this class. This method may be time-consuming.
*
* @param fd the FileDescriptor for the file you want to play
* @throws IllegalArgumentException if the FileDescriptor is invalid
*/
public void setDataSource(FileDescriptor fd)
throws IllegalArgumentException {
// intentionally less than LONG_MAX
setDataSource(fd, 0, 0x7ffffffffffffffL);
}
/**
* Sets the data source as a content Uri. Call this method before
* the rest of the methods in this class. This method may be time-consuming.
*
* @param context the Context to use when resolving the Uri
* @param uri the Content URI of the data you want to play
* @throws IllegalArgumentException if the Uri is invalid
* @throws SecurityException if the Uri cannot be used due to lack of
* permission.
*/
public void setDataSource(Context context, Uri uri)
throws IllegalArgumentException, SecurityException {
if (uri == null) {
throw new IllegalArgumentException();
}
String scheme = uri.getScheme();
if(scheme == null || scheme.equals(“file”)) {
setDataSource(uri.getPath());
return;
}
AssetFileDescriptor fd = null;
try {
ContentResolver resolver = context.getContentResolver();
try {
fd = resolver.openAssetFileDescriptor(uri, “r”);
} catch(FileNotFoundException e) {
throw new IllegalArgumentException();
}
if (fd == null) {
throw new IllegalArgumentException();
}
FileDescriptor descriptor = fd.getFileDescriptor();
if (!descriptor.valid()) {
throw new IllegalArgumentException();
}
// Note: using getDeclaredLength so that our behavior is the same
// as previous versions when the content provider is returning
// a full file.
if (fd.getDeclaredLength() < 0) {
setDataSource(descriptor);
} else {
setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength());
}
return;
} catch (SecurityException ex) {
} finally {
try {
if (fd != null) {
fd.close();
}
} catch(IOException ioEx) {
}
}
setDataSource(uri.toString());
}
/**
* Call this method after setDataSource(). This method retrieves the
* meta data value associated with the keyCode.
*
* The keyCode currently supported is listed below as METADATA_XXX
* constants. With any other value, it returns a null pointer.
*
* @param keyCode One of the constants listed below at the end of the class.
* @return The meta data value associate with the given keyCode on success;
* null on failure.
*/
public native String extractMetadata(int keyCode);
/**
* Call this method after setDataSource(). This method finds a
* representative frame if successful and returns it as a bitmap. This is
* useful for generating a thumbnail for an input media source.
*
* @return A Bitmap containing a representative video frame, which
*         can be null, if such a frame cannot be retrieved.
*/
public native Bitmap captureFrame();
/**
* Call this method after setDataSource(). This method finds the optional
* graphic or album art associated (embedded or external url linked) the
* related data source.
*
* @return null if no such graphic is found.
*/
public native byte[] extractAlbumArt();
/**
* Call it when one is done with the object. This method releases the memory
* allocated internally.
*/
public native void release();
private native void native_setup();
private static native void native_init();
private native final void native_finalize();
@Override
protected void finalize() throws Throwable {
try {
native_finalize();
} finally {
super.finalize();
}
}
public static final int MODE_GET_METADATA_ONLY  = 0×01;
public static final int MODE_CAPTURE_FRAME_ONLY = 0×02;
/*
* Do not change these values without updating their counterparts
* in include/media/mediametadataretriever.h!
*/
public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
public static final int METADATA_KEY_ALBUM           = 1;
public static final int METADATA_KEY_ARTIST          = 2;
public static final int METADATA_KEY_AUTHOR          = 3;
public static final int METADATA_KEY_COMPOSER        = 4;
public static final int METADATA_KEY_DATE            = 5;
public static final int METADATA_KEY_GENRE           = 6;
public static final int METADATA_KEY_TITLE           = 7;
public static final int METADATA_KEY_YEAR            = 8;
public static final int METADATA_KEY_DURATION        = 9;
public static final int METADATA_KEY_NUM_TRACKS      = 10;
public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11;
public static final int METADATA_KEY_CODEC           = 12;
public static final int METADATA_KEY_RATING          = 13;
public static final int METADATA_KEY_COMMENT         = 14;
public static final int METADATA_KEY_COPYRIGHT       = 15;
public static final int METADATA_KEY_BIT_RATE        = 16;
public static final int METADATA_KEY_FRAME_RATE      = 17;
public static final int METADATA_KEY_VIDEO_FORMAT    = 18;
public static final int METADATA_KEY_VIDEO_HEIGHT    = 19;
public static final int METADATA_KEY_VIDEO_WIDTH     = 20;
public static final int METADATA_KEY_WRITER          = 21;
public static final int METADATA_KEY_MIMETYPE        = 22;
public static final int METADATA_KEY_DISCNUMBER      = 23;
public static final int METADATA_KEY_ALBUMARTIST     = 24;
// Add more here…
}




Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法

ps:个人用fat jar。

方案一:用Eclipse自带的Export功能

步骤1:准备主清单文件 “MANIFEST.MF”,

由于是打包引用了第三方jar包的Java项目,故需要自定义配置文件MANIFEST.MF,在该项目下建立文件MANIFEST.MF,内容如下:

Manifest-Version: 1.0
Class-Path: lib/commons-codec.jar lib/commons-httpclient-3.1.jar lib/commons-logging-1.1.jar lib/log4j-1.2.16.jar lib/jackson-all-1.8.5.jar
Main-Class: main.KillCheatFans

第一行是MAINIFEST的版本,第二行Class-Path就指定了外来jar包的位置,第三行指定我们要执行的MAIN java文件。

这里要注意几点:

复制代码
1、Class-Path: 和Main-Class: 后边都有一个空格,必须加上,否则会打包失败,错误提示为:Invalid header field;

2、假设我们的项目打包后为KillCheatFans.jar,那么按照上面的定义,应该在 KillCheatFans.jar的同层目录下建立一个lib文件夹(即lib文件和打包的jar文件
在同一个目录下),并将相关的jar包放在里面。否则将会出现“Exception in thread "main" java.lang.NoClassDefFoundError”的错误;

3、Main-Class后面是类的全地址,比如你的主文件是KillCheatFans.java,文件里打包为package com.main; 那么这里就写com.main.KillCheatFans,
不要加.java后缀,主文件地址写错将会出现“找不到或无法加载主类”的错误;

4、写完Main-Class后一定要回车(即最后一行是空白行),让光标到下一行,这样你生成的jar包才能找到你的主class去运行,

否则将会出现“jar中没有主清单属性”的错误。
复制代码

 

步骤2:右击Java工程选择Export—>选择JAR file—>Next

 [置顶] *知识点积累————温故而知新_第6张图片

步骤3:选择要打包的文件,不需要的文件不必打包,减小打包后的jar文件大小,并进行选项配置如下


这里有几个选项:

* Export generated class files and resources 表示只导出生成的.class文件和其他资源文件
* Export all output folders for checked projects 表示导出选中项目的所有文件夹
* Export java source file and resouces 表示导出的jar包中将包含你的源代码*.java,如果你不想泄漏源代码,那么就不要选这项了
* Export refactorings for checked projects 把一些重构的信息文件也包含进去

 

步骤4:选择我们在第一步中自定义的配置文件路径,这一步很重要,不能采用默认选项

 [置顶] *知识点积累————温故而知新_第7张图片

这里解释一下配置项:

* Generate the manifest file:是系统帮我们自动生成MANIFEST.MF文件,如果你的项目没有引用其他class-path,那可以选择这一项。
* Use existing mainfest from workspace:这是可以选择我们自定义的.MF文件,格式如上所写,引用了第三方包时选用。
* Seal content:要封装整个jar或者指定的包packet。
* Main class:这里可以选择你的程序入口,将来打包出来的jar就是你这个入口类的执行结果。

 

最后Finish,即生成了我们要的jar文件。

 

运行该jar文件有两种方式:

1. 在命令行下运行命令java -jar 你的jar文件名称,比如我的执行如下:


如果在jar中有一些System.out.prinln语句(如上执行结果),运行后不想在控制台输出而是保存在文件中方便以后查看,可以用一下命令:
java -jar KillCheatFans.jar > log.txt (这时命令行窗口不会有任何输出)
输出信息会被打印到log.txt中,当然log.txt自动生成,并位于和KillCheatFans.jar一个目录中。

 

2. 新建一个批处理文件,如start.bat,内容为:java -jar KillCheatFans.jar,放在jar文件同一目录下即可,以后点击自动运行即可,更加方便。

 

方案二:安装Eclipse打包插件Fat Jar

     方案一对于含有较多第三方jar文件或含有第三方图片资源等就显得不合适,太繁琐。这时可以使用一个打包的插件—Fat Jar。

     Fat Jar Eclipse Plug-In是一个可以将Eclipse Java Project的所有资源打包进一个可执行jar文件的小工具,可以方便的完成各种打包任务,我们经常会来打jar包,但是eclipse自带的打包jar似乎不太够用,Fat Jar是eclipse的一个插件,特别是Fat Jar可以打成可执行Jar包,并且在图片等其他资源、引用外包方面使用起来更方便。


安装方法:

1. Eclipse在线更新方法
Help > Install New Software > Add,
name:Fat Jar
location:http://kurucz-grafika.de/fatjar

2. Eclipse插件手动安装方法
下载地址:http://downloads.sourceforge.net/fjep/net.sf.fjep.fatjar_0.0.27.zip?modtime=1195824818&big_mirror=0
将解压出的plugins中的文件复制到eclipse安装目录中的plugins目录下,然后重启eclipse即可。

使用方法:

步骤1:右击工程项目选择Buile Fat Jar

 [置顶] *知识点积累————温故而知新_第8张图片

步骤2:配置jar文件存放目录,主Main文件等,如下图

 [置顶] *知识点积累————温故而知新_第9张图片

步骤3:选择所要用到的第三方jar包

 [置顶] *知识点积累————温故而知新_第10张图片

最后Finish,即生成了我们要的jar文件,十分方便。




删除git中repository后,Android Studio Project 依旧提示“ project is already on GitHub ”

今天把github中的一个repository 删除后,想重新将project分享到github,但是Android Studio Project 依旧提示“ project is already on GitHub ”,即“该项目在github已经存在”。

解决办法:
关闭Android Studio,进入电脑中你要分享的那个项目的目录,假设我这里的项目目录是 C:\Users\HIPAA\AndroidStudioProjects\projectname\,开启“显示隐藏文件”的功能,就能看到隐藏的文件夹/.git  ,打开其中的config文件,删除类似于下面格式的三行:

[remote "origin"]
url = https://github.com/ksharpdabu/projectname.git
fetch = +refs/heads/*:refs/remotes/origin/*

然后保存config文件。重新打开Android Studio,点击“Share project on GitHub”,就不会有“ project is already on GitHub ”的错误提示了。


android studio 如何像ADT 那样,鼠标放在方法上自动提示方法的用法注释


在 Eclipse中鼠标放上去就可以提示方法的用法,实际上Android Studio也可以设置的。

如图 Preferences > Editor >Generan> Show doc on mouse move:勾选上


确定后光标移到方法上:

[置顶] *知识点积累————温故而知新_第11张图片




Android应用程序永久获取root权限方法


原文:http://hold-on.iteye.com/blog/1901152

Android应用程序永久获取root权限方法

    博客分类:
  • Android
  • java

Androidroot权限应用程序永久获取root权限

在项目的过程中,有可能会要实现类似360优化大师、安卓优化大师的软件搬家、静默安装等需要root权限的功能,或者类似SET_PREFERRED_APPLICATIONS、MOVE_PACKAGE 等需要系统的权限,必须要有系统签名。

咱们拿 软件搬家 来当例子(通过获取系统权限,而不是弹出系统的应用管理界面来搬家):

实现方式:

1、想办法获取系统权限,但是这个一般办不到,因为不同厂家出厂的手机系统签名都不一样

(

可以看看我很早的时候提的问题:

android系统权限SET_PREFERRED_APPLICATIONS怎么获取

)

2、在已经root过得手机,获取root权限(有root权限就可以为所欲为啦,嘿嘿)

第一种办法暂时不考虑,想了解的童鞋可以google android如何获取系统权限。

我们说说第二种办法,

在已经root过得手机上获取root权限,简单

Java代码  复制代码  收藏代码
  1. Process process = Runtime.getRuntime().exec("su");
[java]  view plain  copy
  1. Process process = Runtime.getRuntime().exec("su");  

执行这一句,superuser.apk就会弹出授权对话框。

但是这样做就可以了吗.....肯定没这么简单啦!

当执行需要系统权限的操作时,系统还是回去检查应用程序是否拥有该权限。

所以我们要想办法绕过过系统检查权限这道关卡!

至于办法 可以参考下以下两篇博客:

1、android应用搬家的实现

2、如何在Android中启动java程序

大概思路是:

通过app_process 命令启动java程序(想了解app_process更多资料,请自行google),

可是app_process 命令需要root权限才能执行,所以要配合上面所讲的su命令啦。

这么做是可以实现绕过系统检查权限的大门,

但是每次执行的时候都要先请求下root权限(那种弹框和toast会让用户感觉到很不安)

不要忘了咱们的标题:Android应用程序永久获取root权限方法

永久获取root权限,就是获取过一次root权限后,以后再也不需要去请求root权限

实际上,像一些软件管家:安卓优化大师、360优化大师,都是这么做的

(不信你可以试试其软件搬家功能,即使你的手机解除root,它们还是具有root权限)

原理可以看下以下链接:

安卓应用程序永久获取Root权限的方法

(下载该文章需要money,明天我再上传该文档,一时找不到了.......)

大概思路:

自己编译一个类似su的可执行程序(以下以main为代号),在main中调用app_process命令,

然后在第一次获取root权限的时候将其push到/system/bin/目录下,再chmod 4755 可执行程序,

修改其访问权限,使执行该命令的进程能够暂时获得root权限

(4755 也请google下吧 linux文件权限)。

以后咱们要是需要root权限的话就调用mian命令,不用去调用su来请求root权限啦

至于为什么要这么做:也是为了让root授权的对话框和toast不在显示

插一句,想要知道su和superuser.apk的关系,请点开下面的链接

android superuser.apk 管理root权限原理分析

综上:我们所做的就是绕过su命令,用我们自己编写的可执行程序main开实现su的功能。

自己编译可执行程序main的时候,需要注意一点,请参考su源码,

我在这一步就卡了很久,

大概意思:

main的uid是继承的父类的uid,而且它有root权限,但是在main中执行system(cmd),

(这里的cmd 调用app_process 来启动实现了软件搬家的java程序),

假如system()是通过sh 命令来实现,但在main中开启的sh的uid也是继承main的uid,

也就是应用程序的uid,但是这个uid并没有权限执行相关root命令;

所以需要先将main的uid设置为root,为了使sh的uid也为root,从而使sh 能够执行

需要root权限的app_process命令

关键代码在你的main 方法中加入

C代码  复制代码  收藏代码
  1. int uid = 0;
  2. int gid = 0;
  3. if(setgid(gid) || setuid(uid))
  4. return permissionDenied();
[c]  view plain  copy
  1. int uid = 0;  
  2. int gid = 0;  
  3.           
  4. if(setgid(gid) || setuid(uid))   
  5.     return permissionDenied();  

可以参考su的源码 (su的源码会在我上传的压缩包中)

大概思路就是这样。

PS:

在我上传的压缩包中有我自己写的demo,实现的是软件搬家的功能,

操作很简单:

1、安装Movepkgdemo.apk,并执行

2、点击 install com.zl.hw 按钮 来 安装一个helloword android程序,

3、点击 get root 按钮,来第一次获取root权限,

4、点击第三个按钮,来移动helloword程序

PPS:

1、编译可执行程序main(注意main只是个代号,在Movepkgdemo中 是 放在Movepkgdemo项目的 /res/ raw/ 目录下的zlsu文件)

2、将main.c文件成可执行文件会需要linux编译环境,你可以自己在linux上编译,也可以在windows下来编译

windows方法:使用cygwin 来进行NDK开发(搭建该环境可能需要话费比较多时间,主要是要下载cygwin)

cygwin环境配置文档也在上传的压缩包中,虽说花了打功夫,但是搭建好NDK环境,以后也能方便咱做NDK开发。

NDK环境搭建需要cygwin在安装的时候安装必需的一些项目(请查看以下链接):

Cygwin安装

最后总结一下总体思路:

1、在java代码中实现需要root权限的功能,并提供一个包含入口函数main的类

2、通过app_process命令来启动1中的java模块,但是app_process需要root权限,所以看第3步

3、通过在第一次获取root权限的时候,向/system/bin/注入自写的类似su的二进制可执行程序

main,并且和su的访问权限也一样(chmod 4755)(main功能和su一样,唯一不一样就是去除了su中与superuser.apk 交互的代码),即main命令执行app_process命令,这样可以做到:

一旦拥有root权限,以后再也不需要去请求root权限




如何使用Git上传项目代码到github


 这是我第一次应用git,以下仅供git的初学者参考。
     github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开。这对于一般人来说公共仓库就已经足够了。


     1.注册账户以及创建仓库
     要想使用github第一步当然是注册github账号了。之后就可以创建仓库了(免费用户只能建公共仓库),Create a New Repository,填好名称后Create,之后会出现一些仓库的配置信息,这也是一个git的简单教程。


     2.安装客户端tortoiseGit
     github是服务端,要想在自己电脑上使用git我们还需要一个git客户端,我这里选用TortoiseGit,他给我们提供了图形界面的操作。在安装之前首先需要安装git,下载地址http://msysgit.github.com/,TortoiseGit下载地址:
     http://code.google.com/p/tortoisegit/
     装完后右键鼠标会多出一些选项来,在本地仓库里右键选择Git Init Here,会多出来一个.git文件夹,这就表示本地git创建成功。右键Git Bash进入git命令行,为了把本地的仓库传到github,还需要配置ssh key。


     3.配置Git
     (1) 首先在本地创建ssh key;
    $ ssh-keygen -t rsa -C "[email protected]"
 后面的[email protected]改为你的邮箱,之后会要求确认路径和输入密码,我们这使用默认的一路回车就行。成功的话会在~/下生成.ssh文件夹,进去,打开id_rsa.pub,复制里面的key。回到github,进入Account Settings,左边选择SSH Keys,Add SSH Key,title随便填,粘贴key。

 

 (2)为了验证是否成功,在git bash下输入:
    $ ssh -T [email protected]
 如果是第一次的会提示是否continue,输入yes就会看到:You’ve successfully authenticated, but GitHub does not provide shell access 。这就表示已成功连上github。


 

 

 

 

 

 (3)接下来我们要做的就是把本地仓库传到github上去,在此之前还需要设置username和email,因为github每次commit都会记录他们。
 $ git config --global user.name "your name"
 $ git config --global user.name "your name"$ git config --global user.email "[email protected]"
 (4)进入要上传的仓库,右键git bash,添加远程地址:
  $ git remote add origin [email protected]:yourName/yourRepo.git
 后面的yourName和yourRepo表示你再github的用户名和刚才新建的仓库,加完之后进入.git,打开config,这里会多出一个remote “origin”内容,这就是刚才添加的远程地址,也可以直接修改config来配置远程地址。

 

    4.提交、上传
  (1)接下来在本地仓库里添加一些文件,比如README,
   $ git add README
   $ git add README$ git commit -m "first commit"
   (2)上传到github:
   $ git push origin master
   git push命令会将本地仓库推送到远程服务器。
   git pull命令则相反。
   修改完代码后,使用git status可以查看文件的差别,使用git add 添加要commit的文件,也可以用git add -i来智能添加文件。之后git commit提交本次修改,git push上传到github。
 
  5.gitignore文件
 .gitignore顾名思义就是告诉git需要忽略的文件,这是一个很重要并且很实用的文件。一般我们写完代码后会执行编译、调试等操作,这期间会产生很多中间文件和可执行文件,这些都不是代码文件,是不需要git来管理的。我们在git status的时候会看到很多这样的文件,如果用git add -A来添加的话会把他们都加进去,而手动一个个添加的话也太麻烦了。这时我们就需要.gitignore了。比如一般c#的项目我的.gitignore是这样写的:

bin
.suo
obj

bin和obj是编译目录,里面都不是源代码,忽略;suo文件是vs2010的配置文件,不需要。这样你在git status的时候就只会看到源代码文件了,就可以放心的git add -A了。



The following SDK components were not installed


The following SDK components were not installed: platform-tools, extra-android-m2repository, tools, addon-google_apis-google-21, build-tools-21.1.1, android-21, sys-img-x86-addon-google_apis-google-21, source-21, extra-google-m2repository

这个问题产生的原因是 sdk 目录跟 没有找到,解决办法是:

把SDK安装目录下的android-sdk文件夹下的所有文件剪切到上层SDK目录下,重新打开Android程序,报错消失




*gen already exists but is not a source folder. Convert to a source folder or rename it的错误


转自: http://yxwang0615.iteye.com/blog/1849965

遇到android项目导入出现后重复空包等错误,往往是导入的java编译级别有关,点击项目properties->

java Compiler ->修改Compiler compliance level 一般是1.6。

修改完成clean项目之后,往往还会遇到:

gen already exists but is not a source folder. Convert to a source folder or rename it的错误。

 

遇到这个问题的解决方法:

 1. 右键点击工程,选择 "Properties"

2. 选择左边的 "Java Build Path" 

3. 打开 "Source" 标签面板

4. 点击 "Add Folder..."

5. 勾选 "gen" 文件夹,点击OK,点击YES,再点击OK

6. 最后右键点击工程,选择 "Andriod Tools" 里面的 "Fix Project Properties"

 

出现这个问题的原因是classpath文件出错,这个文件存在于项目根目录下,是eclipse自动生成的,它定义了你这个项目在编译时所使用的$CLASSPATH,一般不需要手动配置。如果出错,也可手动修改:

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <classpath>  
  3.     <classpathentry kind="src" path="src"/>  
  4.     <classpathentry kind="src" path="gen"/>  
  5.     <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>  
  6.     <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>  
  7.     <classpathentry kind="lib" path="libs/ksoap2-android-assembly-2.5.8-jar-with-dependencies.jar"/>  
  8.     <classpathentry kind="output" path="bin/classes"/>  
  9. </classpath>  

 

从数据上我们容易看出,上面描述了工程的依赖文件:

源文件的具体位置(kind="src")

运行的系统环境(kind="con")

工程的library的具体位置信息(kind="lib")

项目的输出目录(kind="output")



Android开发中设置Dialog不允许返回


1. 最简单的setCancelable(false)

2. alertDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
   @Override
   public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
   {
   if (keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0)
    {
     return true;
    }
    else
    {
     return false; //默认返回 false,这里false不能屏蔽返回键,改成true就可以了
    }
   }
  });


No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案


这个问题的产生是由于缺少Theme.AppCompat.Light这个主题产生的,而这个主题 的是存在于android\support\appcompat-v7支持库中

No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案是
第一步:
    从网上下载appcompat-v7工程库也可以直接在 sdk路径\extras\android\support\v7[置顶] *知识点积累————温故而知新_第12张图片中找到。
第二步:
   把工程库导入到Eclipse ,[置顶] *知识点积累————温故而知新_第13张图片,跟导入工程一样。

第三步:
   项目右键--------Properties------android----add-----选择上一步导入的lib库-----ok
   [置顶] *知识点积累————温故而知新_第14张图片
导入成功状态
[置顶] *知识点积累————温故而知新_第15张图片如果为红色xx则导入不成功


到此结束,最后看看原先有错的工程。是不是已经没问题了



获取Android手机CPU类型 ARM、ARMV7、NEON

1 查看手机CPU信息

cmd——adb shell——cd /proc------cat cpuinfo

[置顶] *知识点积累————温故而知新_第16张图片

2 获取cpu的是arm指令集,armv7指令集、还是neon指令集

[java]  view plain copy
  1. /** 
  2.  *  
  3.  * [获取cpu类型和架构] 
  4.  *  
  5.  * @return  
  6.  * 三个参数类型的数组,第一个参数标识是不是ARM架构,第二个参数标识是V6还是V7架构,第三个参数标识是不是neon指令集 
  7.  */  
  8. public static Object[] getCpuArchitecture() {  
  9.     if ((Integer) mArmArchitecture[1] != -1) {  
  10.         return mArmArchitecture;  
  11.     }  
  12.     try {  
  13.         InputStream is = new FileInputStream("/proc/cpuinfo");  
  14.         InputStreamReader ir = new InputStreamReader(is);  
  15.         BufferedReader br = new BufferedReader(ir);  
  16.         try {  
  17.             String nameProcessor = "Processor";  
  18.             String nameFeatures = "Features";  
  19.             String nameModel = "model name";  
  20.             String nameCpuFamily = "cpu family";  
  21.             while (true) {  
  22.                 String line = br.readLine();  
  23.                 String[] pair = null;  
  24.                 if (line == null) {  
  25.                     break;  
  26.                 }  
  27.                 pair = line.split(":");  
  28.                 if (pair.length != 2)  
  29.                     continue;  
  30.                 String key = pair[0].trim();  
  31.                 String val = pair[1].trim();  
  32.                 if (key.compareTo(nameProcessor) == 0) {  
  33.                     String n = "";  
  34.                     for (int i = val.indexOf("ARMv") + 4; i < val.length(); i++) {  
  35.                         String temp = val.charAt(i) + "";  
  36.                         if (temp.matches("\\d")) {  
  37.                             n += temp;  
  38.                         } else {  
  39.                             break;  
  40.                         }  
  41.                     }  
  42.                     mArmArchitecture[0] = "ARM";  
  43.                     mArmArchitecture[1] = Integer.parseInt(n);  
  44.                     continue;  
  45.                 }  
  46.   
  47.                 if (key.compareToIgnoreCase(nameFeatures) == 0) {  
  48.                     if (val.contains("neon")) {  
  49.                         mArmArchitecture[2] = "neon";  
  50.                     }  
  51.                     continue;  
  52.                 }  
  53.   
  54.                 if (key.compareToIgnoreCase(nameModel) == 0) {  
  55.                     if (val.contains("Intel")) {  
  56.                         mArmArchitecture[0] = "INTEL";  
  57.                         mArmArchitecture[2] = "atom";  
  58.                     }  
  59.                     continue;  
  60.                 }  
  61.   
  62.                 if (key.compareToIgnoreCase(nameCpuFamily) == 0) {  
  63.                     mArmArchitecture[1] = Integer.parseInt(val);  
  64.                     continue;  
  65.                 }  
  66.             }  
  67.         } finally {  
  68.             br.close();  
  69.             ir.close();  
  70.             is.close();  
  71.         }  
  72.     } catch (Exception e) {  
  73.         e.printStackTrace();  
  74.     }  
  75.   
  76.     return mArmArchitecture;  
  77. }  

调用的该函数的示例方法

[java]  view plain copy
  1. /* 
  2.  * 获取FFpeg解码库的名称(如果是插件,会涉及到一个向下兼容的问题,例如:如果当前cpu是V7neo,而又没有neon的解码库,必须要做向下兼容出来 
  3.  * ,如果有V7的库就加载V7的库,有V6的库就加载V6的) 
  4.  */  
  5. public static String getFFmpegLibName(Context context) {  
  6.     if (LIB_FFMPEG_NAME != null) {  
  7.         return LIB_FFMPEG_NAME;  
  8.     }  
  9.     Object[] arch = getCpuArchitecture();  
  10.   
  11.     String libDir = getNativeLibraryDir(context);  
  12.     String libSysDir = "/system/lib";  
  13.   
  14.     if ("ARM".equals(arch[0])) {  
  15.         try {  
  16.             String ffmpeg = String.format("ffmpeg-%d%s", (Integer) arch[1], (String) arch[2]);  
  17.             if (isFileExist(libDir + "/lib" + ffmpeg + ".so") || isFileExist(libSysDir + "/lib" + ffmpeg + ".so")) {  
  18.                 return ffmpeg;  
  19.             } else {  
  20.                 boolean isV7NeonCpu = "neon".equals(arch[2]);  
  21.                 boolean isV7 = ((Integer) arch[1]) == 7 && "".equals(arch[2]);  
  22.                 boolean isV6 = ((Integer) arch[1]) == 6;  
  23.                 if (isV7NeonCpu) {  
  24.                     if (isFileExist(libDir + "/libffmpeg-7neon.so")  
  25.                             || isFileExist(libSysDir + "/libffmpeg-7neon.so")) {  
  26.                         LIB_FFMPEG_NAME = "ffmpeg-7neon";  
  27.                         return "ffmpeg-7neon";  
  28.                     } else if (isFileExist(libDir + "/libffmpeg-7.so")  
  29.                             || isFileExist(libSysDir + "/libffmpeg-7.so")) {  
  30.                         LIB_FFMPEG_NAME = "ffmpeg-7";  
  31.                         return "ffmpeg-7";  
  32.                     } else if (isFileExist(libDir + "/libffmpeg-6.so")  
  33.                             || isFileExist(libSysDir + "/libffmpeg-6.so")) {  
  34.                         LIB_FFMPEG_NAME = "ffmpeg-6";  
  35.                         return "ffmpeg-6";  
  36.                     }  
  37.                 } else if (isV7) {  
  38.                     if (isFileExist(libDir + "/libffmpeg-7.so") || isFileExist(libSysDir + "/libffmpeg-7.so")) {  
  39.                         LIB_FFMPEG_NAME = "ffmpeg-7";  
  40.                         return "ffmpeg-7";  
  41.                     } else if (isFileExist(libDir + "/libffmpeg-6.so")  
  42.                             || isFileExist(libSysDir + "/libffmpeg-6.so")) {  
  43.                         LIB_FFMPEG_NAME = "ffmpeg-6";  
  44.                         return "ffmpeg-6";  
  45.                     }  
  46.                 } else if (isV6) {  
  47.                     if (isFileExist(libDir + "/libffmpeg-6.so") || isFileExist(libSysDir + "/libffmpeg-6.so")) {  
  48.                         LIB_FFMPEG_NAME = "ffmpeg-6";  
  49.                         return "ffmpeg-6";  
  50.                     }  
  51.                 }  
  52.             }  
  53.         } catch (Exception e) {  
  54.             e.printStackTrace();  
  55.         }  
  56.     } else if ("INTEL".equals(arch[0])) {  
  57.         if (isFileExist(libDir + "/libffmpeg-x86atom.so") || isFileExist(libSysDir + "/libffmpeg-x86atom.so")) {  
  58.             LIB_FFMPEG_NAME = "ffmpeg-x86atom";  
  59.             return "ffmpeg-x86atom";  
  60.         }  
  61.     }  
  62.     LIB_FFMPEG_NAME = null;  
  63.     return null;  
  64. }  


设置Activity背景色为透明的2种方法

android设置背景色为透明
方法一:
只要在配置文件内activity属性配置内加上
android:theme="@android:style/Theme.Translucent" 
就好了。
这样就调用了android的透明样式!
方法二:
先在res/values下建colors.xml文件,写入:
<span style="font-family:SimHei;font-size:14px;">  <resources>
  <colorname="transparent">#9000</color>
  </resources></span>


  这个值设定了整个界面的透明度,为了看得见效果,现在设为透明度为56%(9/16)左右。
  再在res/values/下建styles.xml,设置程序的风格
<span style="font-family:SimHei;font-size:14px;">  <resources>
  <stylename="Transparent">
  <itemname="android:windowBackground">@color/transparent</item>
  <itemname="android:windowIsTranslucent">true</item>
  <itemname="android:windowAnimationStyle">@+android:style/Animation.Translucent</item>
  </style>
  </resources></span>


  最后一步,把这个styles.xml用在相应的Activity上。即在AndroidManifest.xml中的任意<activity>标签中添加
  android:theme="@style/transparent"
  如果想设置所有的activity都使用这个风格,可以把这句标签语句添加在<application>中。
  最后运行程序,哈哈,是不是发现整个界面都被蒙上一层半透明了。最后可以把背景色#9000换成#0000,运行程序后,就全透明了,看得见背景下的所有东西可以却都操作无效。




android:descendantFocusability用法简析

原文 地址 http://www.cnblogs.com/eyu8874521/archive/2012/10/17/2727882.html

android:descendantFocusability用法简析

    开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

    这时候就可以使用descendantFocusability来解决啦,API描述如下:

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

 

该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

属性的值有三种:

        beforeDescendants:viewgroup会优先其子类控件而获取到焦点

        afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

        blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

 

通常我们用到的是第三种,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的属性就好了,至此listview点击的灵异事件告一段落。心得:遇到不会不懂的地方除了网上查询资料之外,也可以多多去尝试每种属性的作用,多阅读官方文档(我始终觉得还是读原文的比翻译的理解的会更好)。





原文 地址 http://www.cnblogs.com/eyu8874521/archive/2012/10/17/2727882.html

android:descendantFocusability用法简析

    开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

    这时候就可以使用descendantFocusability来解决啦,API描述如下:

android:descendantFocusability

Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.

Must be one of the following constant values.

 

该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

属性的值有三种:

        beforeDescendants:viewgroup会优先其子类控件而获取到焦点

        afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

        blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

 

通常我们用到的是第三种,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的属性就好了,至此listview点击的灵异事件告一段落。心得:遇到不会不懂的地方除了网上查询资料之外,也可以多多去尝试每种属性的作用,多阅读官方文档(我始终觉得还是读原文的比翻译的理解的会更好)。



android有序广播和无序广播的区别


BroadcastReceiver的区别细究

1.android有序广播和无序广播的区别 

BroadcastReceiver所对应的广播分两类:普通广播和有序广播。 

普通广播通过Context.sendBroadcast()方法来发送。它是完全异步的。 

所有的receivers接收器的执行顺序不确定。    因此,所有的receivers接收器接收broadcast的顺序不确定。 

这种方式效率更高。但是BroadcastReceiver无法使用setResult系列,getResult系列及abort系列API 

有序广播是通过Context.sendOrderedBroadcast来发送。所有的receiver依次执行。 

BroadcastReceiver可以使用setResult系列函数来结果传给下一个BroadcastReceiver,通过getResult系列函数来取得上个BroadcastReceiver返回的结果,并可以abort系列函数来让系统丢弃该广播让,使用该广播不再传送到别的BroadcastReceiver。 

可以通过在intent-filter中设置android:priority属性来设置receiver的优先级。优先级相同的receiver其执行顺序不确定。 

如果BroadcastReceiver是代码中注册的话,且其intent-filter拥有相同android:priority属性的话,先注册的将先收到广播。 

有序广播,即从优先级别最高的广播接收器开始接收,接收完了如果没有丢弃,就下传给下一个次高优先级别的广播接收器进行处理,依次类推,直到最后。 

2.sendBroadcast和sendStickyBroadcast的区别 

sendBroadcast中发出的intent在ReceverActivity不处于onResume状态是无法接受到的,即使后面再次使其处于该状态也无法接受到。 

而sendStickyBroadcast发出的Intent当ReceverActivity重新处于onResume状态之后就能重新接受到其Intent.这就是the Intent will be held to be re-broadcast to future receivers这句话的表现。就是说sendStickyBroadcast发出的最后一个Intent会被保留,下次当Recevier处于活跃的时候,又会接受到它。 

3. FLAG的影响 
1)FLAG_RECEIVER_REPLACE_PENDING 
这个flag 将会将之前的Intent 替代掉。加了这个flag,在发送一系列的这样的Intent 之后, 中间有些Intent 有可能在你还没有来得及处理的时候,就被替代掉了。 
2)FLAG_RECEIVER_REGISTERED_ONLY: 
如果Intent 加了这个Flag, 那么在Androidmanifest.xml 里定义的Receiver 是接收不到这样的Intent 的。 
3)FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT: 
如果Intent加了这个Flag,那么在启动检查时只能接受在代码中注册的Receiver。这个标志是唯一使用的系统服务作为一种方便避免实施更复杂的机制在启动完成检测。 


[Android] ImageView.ScaleType设置图解

ImageView的Scaletype决定了图片在View上显示时的样子,如进行何种比例的缩放,及显示图片的整体还是部分,等等。

设置的方式包括:

1. 在layout xml中定义android:scaleType="CENTER"

2. 或在代码中调用imageView.setScaleType(ImageView.ScaleType.CENTER);


接下来,将对ScaleType的值和对应的显示效果用最直观的方式——真图演示的方法,来进行说明。


首先,是测试使用的原始图片:

[置顶] *知识点积累————温故而知新_第17张图片(Dimensions: 128 * 128)

[置顶] *知识点积累————温故而知新_第18张图片 (Dimensions: 640 * 428)


好,开始下面的测试:

1. SetScaleType(ImageView.ScaleType.CENTER);

    按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示

[置顶] *知识点积累————温故而知新_第19张图片               [置顶] *知识点积累————温故而知新_第20张图片


2. SetScaleType(ImageView.ScaleType.CENTER_CROP);

    按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽) 

[置顶] *知识点积累————温故而知新_第21张图片               [置顶] *知识点积累————温故而知新_第22张图片


3. setScaleType(ImageView.ScaleType.CENTER_INSIDE);

    将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽 

[置顶] *知识点积累————温故而知新_第23张图片               [置顶] *知识点积累————温故而知新_第24张图片


4. setScaleType(ImageView.ScaleType.FIT_CENTER);

    把图片按比例扩大/缩小到View的宽度,居中显示

[置顶] *知识点积累————温故而知新_第25张图片               [置顶] *知识点积累————温故而知新_第26张图片


5. FIT_START, FIT_END在图片缩放效果上与FIT_CENTER一样,只是显示的位置不同,FIT_START是置于顶部,FIT_CENTER居中,FIT_END置于底部。

    在此就不给出示例了。


6. FIT_XY

    不按比例缩放图片,目标是把图片塞满整个View。

[置顶] *知识点积累————温故而知新_第27张图片               [置顶] *知识点积累————温故而知新_第28张图片


http://blog.csdn.net/larryl2003/article/details/6919513







ScrollView 嵌套 Listview 显示不完全只显示一条的解决方案


from  http://www.cnblogs.com/shuaiwen/archive/2013/07/26/3217555.html


显示不全 是因为 其 measure  方法 测量 listview 高度计算不正确, 需要重写。  这里 直接 继承父类   重写一下 父类方法  然后 用 自己定义的 listview  gridview  则 可以 全部呈现 数据,不会与 scrollview  冲突。



public class MyListView extends ListView {
	public MyListView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyListView(Context context) {
		super(context);
	}

	public MyListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// 重写 onMeasure 动态计算 listview 高度
		int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
		super.onMeasure(widthMeasureSpec, expandSpec);
	}
}




 
    



你可能感兴趣的:(java,android,String)