[置顶] Android开发百科全书

时间:2023-03-09 22:25:45
[置顶]
        Android开发百科全书

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

%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. 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

效果也不错

[置顶]
        Android开发百科全书

布局

<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);
	}

}

浸入状态栏

[置顶]
        Android开发百科全书

在 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();
	  }
}

-----------------------------------------------------------------------------------------------------------------------

[置顶]
        Android开发百科全书

[置顶]
        Android开发百科全书

代码设置 样式

     // 文字
            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的视图时,在加载视图时总是会把输入的焦点自动移动到第一个输入框。如下图所示:

[置顶]
        Android开发百科全书

下面是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>

最终效果如下所示:

[置顶]
        Android开发百科全书

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

Android 禁止软键盘自动弹出

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

[html] view plaincopy
  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 plaincopy
  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 plaincopy
  1. TextView config_hidden = (TextView) this.findViewById(R.id.config_hidden);
[java] view plaincopy
  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. @Override
  3. public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
  4. int arg2, long arg3) {
  5. // TODO Auto-generated method stub
  6. Log.e("setOnItemLongClickListener", "setOnItemLongClickListener");
  7. return true;
  8. }
  9. });
  10. gridview.setOnItemClickListener(new OnItemClickListener(){
  11. @Override
  12. public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
  13. long arg3) {
  14. Log.e("setOnItemClickListener", "setOnItemClickListener");
  15. }
  16. });

在处理长按时,注意的细节是把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文件。

这里要注意几点:

[置顶]
        Android开发百科全书
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中没有主清单属性”的错误。
[置顶]
        Android开发百科全书

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

[置顶]
        Android开发百科全书

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

[置顶]
        Android开发百科全书

这里有几个选项:

* 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:选择我们在第一步中自定义的配置文件路径,这一步很重要,不能采用默认选项

[置顶]
        Android开发百科全书

这里解释一下配置项:

* 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文件名称,比如我的执行如下:

[置顶]
        Android开发百科全书

如果在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

[置顶]
        Android开发百科全书

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

[置顶]
        Android开发百科全书

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

[置顶]
        Android开发百科全书

最后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,进入电脑中你要分享的那个项目的目录,假设我这里的项目目录是] != -1) {

  • return mArmArchitecture;
  • }
  • try {
  • InputStream is = new FileInputStream("/proc/cpuinfo");
  • InputStreamReader ir = new InputStreamReader(is);
  • BufferedReader br = new BufferedReader(ir);
  • try {
  • String nameProcessor = "Processor";
  • String nameFeatures = "Features";
  • String nameModel = "model name";
  • String nameCpuFamily = "cpu family";
  • while (true) {
  • String line = br.readLine();
  • String[] pair = null;
  • if (line == null) {
  • break;
  • }
  • pair = line.split(":");
  • if (pair.length != 2)
  • continue;
  • String key = pair[0].trim();
  • String val = pair[1].trim();
  • if (key.compareTo(nameProcessor) == 0) {
  • String n = "";
  • for (int i = val.indexOf("ARMv") + 4; i < val.length(); i++) {
  • String temp = val.charAt(i) + "";
  • if (temp.matches("\\d")) {
  • n += temp;
  • } else {
  • break;
  • }
  • }
  • mArmArchitecture[0] = "ARM";
  • mArmArchitecture[1] = Integer.parseInt(n);
  • continue;
  • }
  • if (key.compareToIgnoreCase(nameFeatures) == 0) {
  • if (val.contains("neon")) {
  • mArmArchitecture[2] = "neon";
  • }
  • continue;
  • }
  • if (key.compareToIgnoreCase(nameModel) == 0) {
  • if (val.contains("Intel")) {
  • mArmArchitecture[0] = "INTEL";
  • mArmArchitecture[2] = "atom";
  • }
  • continue;
  • }
  • if (key.compareToIgnoreCase(nameCpuFamily) == 0) {
  • mArmArchitecture[1] = Integer.parseInt(val);
  • continue;
  • }
  • }
  • } finally {
  • br.close();
  • ir.close();
  • is.close();
  • }
  • } catch (Exception e) {
  • e.printStackTrace();
  • }
  • return mArmArchitecture;
  • }
  • ])) {

  • try {
  • String ffmpeg = String.format("ffmpeg-%d%s", (Integer) arch[1], (String) arch[2]);
  • if (isFileExist(libDir + "/lib" + ffmpeg + ".so") || isFileExist(libSysDir + "/lib" + ffmpeg + ".so")) {
  • return ffmpeg;
  • } else {
  • boolean isV7NeonCpu = "neon".equals(arch[2]);
  • boolean isV7 = ((Integer) arch[1]) == 7 && "".equals(arch[2]);
  • boolean isV6 = ((Integer) arch[1]) == 6;
  • if (isV7NeonCpu) {
  • if (isFileExist(libDir + "/libffmpeg-7neon.so")
  • || isFileExist(libSysDir + "/libffmpeg-7neon.so")) {
  • LIB_FFMPEG_NAME = "ffmpeg-7neon";
  • return "ffmpeg-7neon";
  • } else if (isFileExist(libDir + "/libffmpeg-7.so")
  • || isFileExist(libSysDir + "/libffmpeg-7.so")) {
  • LIB_FFMPEG_NAME = "ffmpeg-7";
  • return "ffmpeg-7";
  • } else if (isFileExist(libDir + "/libffmpeg-6.so")
  • || isFileExist(libSysDir + "/libffmpeg-6.so")) {
  • LIB_FFMPEG_NAME = "ffmpeg-6";
  • return "ffmpeg-6";
  • }
  • } else if (isV7) {
  • if (isFileExist(libDir + "/libffmpeg-7.so") || isFileExist(libSysDir + "/libffmpeg-7.so")) {
  • LIB_FFMPEG_NAME = "ffmpeg-7";
  • return "ffmpeg-7";
  • } else if (isFileExist(libDir + "/libffmpeg-6.so")
  • || isFileExist(libSysDir + "/libffmpeg-6.so")) {
  • LIB_FFMPEG_NAME = "ffmpeg-6";
  • return "ffmpeg-6";
  • }
  • } else if (isV6) {
  • if (isFileExist(libDir + "/libffmpeg-6.so") || isFileExist(libSysDir + "/libffmpeg-6.so")) {
  • LIB_FFMPEG_NAME = "ffmpeg-6";
  • return "ffmpeg-6";
  • }
  • }
  • }
  • } catch (Exception e) {
  • e.printStackTrace();
  • }
  • } else if ("INTEL".equals(arch[0])) {
  • if (isFileExist(libDir + "/libffmpeg-x86atom.so") || isFileExist(libSysDir + "/libffmpeg-x86atom.so")) {
  • LIB_FFMPEG_NAME = "ffmpeg-x86atom";
  • return "ffmpeg-x86atom";
  • }
  • }
  • LIB_FFMPEG_NAME = null;
  • return null;
  • }