命令:
生成keystone(存放一组证书和私钥的地方)
keytool -genkey -alias(别名) hello -keyalg RSA -validity 20000 -keystore hello.keystore
查看keystore 信息
keytool -list -v -keystore hello.keystore -storepass 123456
缺省情况下,-list 命令打印证书的 MD5 指纹。而如果指定了 -v 选项,将以可读格式打印证书,如果指定了 -rfc 选项,将以可打印的编码格式输出证书。
keytool -list -rfc -keystore hello.keystore -storepass 123456
证书的导出:
keytool -export -alias test -keystore hello.keystore -file test.crt -storepass 123456
证书的导入
keytool -import -alias rootcert -file root.crt -keystore hello.keystore
证书条目的删除:
keytool -delete -alias ceatecert1 -keystore .keystore -storepass 123456
使用jdk的jarsigner工具对apk文件签名
jarsigner -verbose -keystore hello.keystore TestApk.apk test
签名后可以使用如下命令验证是否签名成功:
jarsigner -verify to_sign.apk
如果需要查看更详细的验证信息,可修改为:
jarsigner -certs -verbose -verify to_sign.apk
获取证书信息相关方法:
package com.nec.test; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.security.KeyStore; import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import android.app.Activity; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.os.Bundle; import android.os.Environment; import android.util.DisplayMetrics; import android.util.Log; public class TestApkActivity extends Activity { /** Called when the activity is first created. */ private static final String FILENAME = "cacerts.bks"; private static final String FILENAME_CERT = "ca.crt"; //test.crt \ ca.crt private List<PublicKey> listKey = new ArrayList<PublicKey>(); private File file; static final String IN_FILE_NAME = "c:\\Documents and Settings\\2172980000522\\TestApk.apk"; static final String OUT_FILE_NAME = "c:\\Documents and Settings\\2172980000522\\TestApk.Zip"; private final static String PATH = "/sdcard/fcding.apk"; // TestApk.apk @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // readCacerts(FILENAME); try { readCert(FILENAME_CERT); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } TestApkActivity activity = new TestApkActivity(); PackageInfo pi = activity.parsePackage(PATH, PackageManager.GET_SIGNATURES); String issuerDN = null; String subjectDN = null; String publickey = null; try { byte[] signature = pi.signatures[0].toByteArray(); // String hash = md5(signature); CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) certFactory.generateCertificate( new ByteArrayInputStream(signature)); issuerDN = cert.getIssuerDN().toString(); Log.d("TRACK", issuerDN); subjectDN = cert.getSubjectDN().toString(); Log.d("TRACK", subjectDN); publickey = cert.getPublicKey().toString(); Log.d("TRACK", publickey); System.out.println("====================++++++++++++++++++++"+listKey.contains(cert.getPublicKey()) ); } catch (CertificateException e) { e.printStackTrace(); } } private PackageInfo parsePackage(String archiveFilePath, int flags){ PackageParser packageParser = new PackageParser(archiveFilePath); DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); final File sourceFile = new File(archiveFilePath); PackageParser.Package pkg = packageParser.parsePackage( sourceFile, archiveFilePath, metrics, 0); if (pkg == null) { return null; } packageParser.collectCertificates(pkg, 0); return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0); } private void readCert(String fileName) throws Exception{ try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream in = getAssets().open(fileName); Certificate c = cf.generateCertificate(in); PublicKey publicKey = c.getPublicKey(); listKey.add(publicKey); System.out.println("********---------------**********"+publicKey.toString()); } catch (Exception e) { e.printStackTrace(); } } private void readCacerts(String filename) { try { InputStream inputStream = getAssets().open(filename); KeyStore keyStore = KeyStore.getInstance("bks"); keyStore.load(inputStream, null); file = new File(Environment.getExternalStorageDirectory(), "a.txt"); getApplication().openFileOutput("a.txt", Context.MODE_APPEND); FileOutputStream outputStream = new FileOutputStream(file); copyStream(keyStore, outputStream); Log.i(TAG, "File create Success"); } catch (Exception e) { e.printStackTrace(); } } private void copyStream(KeyStore keyStore, OutputStream fileOutputStream) throws Exception { Enumeration<String> enumeration = keyStore.aliases(); while (enumeration.hasMoreElements()) { String element = enumeration.nextElement(); Certificate certificate = keyStore.getCertificate(element); listKey.add(certificate.getPublicKey()); String content = certificate.toString(); System.out.println("================"+content); fileOutputStream.write(content.getBytes()); } } }
第一步:在Recovery里对 SD卡进行分区 :
分区后MIUI默认支持A2SD+,分区后SD卡内容会丢失,切记分区前一定要备份。
操作步骤:
1.开机
按住电源键不放直到出现菜单,按音量键选择
"Boot AD SD ",按拨号键确认
2.选择:advance --> partition sd --> ext --> 1024 -->256 。
这样就会在SD卡创建一个1G大小的 ext3分区和一个256M的swap。
第二步:开启 A2SD+
第一步只是支持 A2SD+,但是你发现你装的软件还是装在系统内存里的, A2SD+的可用空间还是1G,需要进行下面的步骤才能完全使用 A2SD+。 到MIUI系统自带的“MIUI网盘”下载“终端模拟器”这个程序,安装运行后输入以下命令:
su 回车
a2sd reinstall 回车
su 回车
a2sd zipalign 回车
a2sd cachesd 回车 手机自动重启,搞定,开始爽吧!
MP3播放器项目---编写代码---6
1. Mp3ListActivity
package hui.mp3player; import hui.download.HttpDownloader; import hui.model.Mp3Info; import hui.xml.Mp3ListContentHandler; import java.io.InputStreamReader; import java.io.StringReader; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.xml.parsers.SAXParserFactory; import hui.mp3player.R; import hui.download.*; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import hui.mp3player.*; import android.R.xml; import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ListView; import android.widget.SimpleAdapter; public class Mp3ListActivity extends ListActivity { private static final int UPDATE = 1; private static final int ABOUT = 2; private List<Mp3Info> mp3Infos = null; private static final String XML_URL=null; /** * 在用点击MENU按钮之后,会调用该方法,我们可以在这个方法当中加入自己的按钮控件 */ @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub menu.add(0, UPDATE, 1, R.string.mp3list_update); menu.add(0, ABOUT, 2, R.string.mp3list_about); return super.onCreateOptionsMenu(menu); } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.remote_mp3_list); updateListView(); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == UPDATE) { updateListView(); } else if (item.getItemId() == ABOUT) { // 用户点击了关于按钮 } return super.onOptionsItemSelected(item); } private SimpleAdapter buildSimpleAdapter(List<Mp3Info> mp3Infos) { // 生成一个List对象,并按照SimpleAdapter的标准,将mp3Infos当中的数据添加到List当中去 List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>(); for (Iterator iterator = mp3Infos.iterator(); iterator.hasNext();) { Mp3Info mp3Info = (Mp3Info) iterator.next(); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("mp3_name", mp3Info.getMp3Name()); map.put("mp3_size", mp3Info.getMp3Size()); map.put("mp3_icon", R.drawable.kky); //map.put("mp3_icon", R.drawable.i2); //map.put("mp3_icon", R.drawable.i3); list.add(map); } // 创建一个SimpleAdapter对象 SimpleAdapter simpleAdapter = new SimpleAdapter(this, list, R.layout.mp3info_item, new String[] { "mp3_name", "mp3_size","mp3_icon" }, new int[] { R.id.mp3_name, R.id.mp3_size,R.id.mp3_icon }); // 将这个SimpleAdapter对象设置到ListActivity当中 return simpleAdapter; } private void updateListView() { // 用户点击了更新列表按钮 // 下载包含所有Mp3基本信息的xml文件 String xml = downloadXML("http://192.168.1.2:8080/myapp/11.xml"); // 对xml文件进行解析,并将解析的结果放置到Mp3Info对象当中,最后将这些Mp3Info对象放置到List当中 mp3Infos = parse(xml); SimpleAdapter simpleAdapter = buildSimpleAdapter(mp3Infos); setListAdapter(simpleAdapter); } private String downloadXML(String urlStr) { HttpDownloader httpDownloader = new HttpDownloader(); String result = httpDownloader.download(urlStr); return result; } private List<Mp3Info> parse(String xmlStr) { SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); List<Mp3Info> infos = new ArrayList<Mp3Info>(); try { URL url=new URL("http://192.168.1.2:8080/myapp/11.xml"); //System.out.print("url-------"+url); //Mp3Info mp3info = new Mp3Info(); //Mp3Info mp3Info1 = mp3Info1.getMp3Name(); //String uriStr=XML_URL+URLEncoder.encode(mp3Info1.getMp3Name(),"UTF-8"); //URL url=new URL(/blog_article/uriStr/index.html); XMLReader xmlReader = saxParserFactory.newSAXParser() .getXMLReader(); Mp3ListContentHandler mp3ListContentHandler = new Mp3ListContentHandler( infos); xmlReader.setContentHandler(mp3ListContentHandler); InputStreamReader isr =new InputStreamReader(url.openStream(),"GB2312"); //StringReader stringReader = new StringReader(resultStr); InputSource inputSource = new InputSource(isr); //StringReader stringReader = new StringReader(xmlStr); //InputSource inputSource = new InputSource(stringReader); xmlReader.parse(inputSource); for (Iterator iterator = infos.iterator(); iterator.hasNext();) { Mp3Info mp3Info = (Mp3Info) iterator.next(); System.out.println("显示111-------"+mp3Info); } } catch (Exception e) { e.printStackTrace(); } return infos; } @Override protected void onListItemClick(ListView l, View v, int position, long id) { // 根据用户点击列表当中的位置来得到响应的Mp3Info对象 Mp3Info mp3Info = mp3Infos.get(position); // 生成Intent对象 Intent intent = new Intent(); System.out.print("点击-----"+ mp3Info); // 将Mp3Info对象存入到Intent对象当中 intent.putExtra("mp3Info", mp3Info); intent.setClass(this, DownloadService.class); // 启动Service startService(intent); super.onListItemClick(l, v, position, id); } }
2.PlayerActivity
package hui.mp3player; import hui.lrc.LrcProcessor; import hui.model.Mp3Info; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.Queue; import hui.mp3player.R; import android.app.Activity; import android.content.Intent; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; import android.widget.TextView; public class PlayerActivity extends Activity { ImageButton beginButton = null; ImageButton pauseButton = null; ImageButton stopButton = null; MediaPlayer mediaPlayer = null; private ArrayList<Queue> queues = null; private TextView lrcTextView = null; private Mp3Info mp3Info = null; private Handler handler = new Handler(); private UpdateTimeCallback updateTimeCallback = null; private long begin = 0; private long nextTimeMill = 0; private long currentTimeMill = 0; private String message = null; private long pauseTimeMills = 0; private boolean isPlaying = false; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.player); Intent intent = getIntent(); mp3Info = (Mp3Info) intent.getSerializableExtra("mp3Info"); beginButton = (ImageButton) findViewById(R.id.begin); pauseButton = (ImageButton) findViewById(R.id.pause); stopButton = (ImageButton) findViewById(R.id.stop); beginButton.setOnClickListener(new BeginButtonListener()); pauseButton.setOnClickListener(new PauseButtonListener()); stopButton.setOnClickListener(new StopButtonListener()); lrcTextView = (TextView)findViewById(R.id.lrcText); } /** * 根据歌词文件的名字,来读取歌词文件当中的信息 * @param lrcName */ private void prepareLrc(String lrcName){ try { InputStream inputStream = new FileInputStream(Environment.getExternalStorageDirectory().getAbsoluteFile() +File.separator + "mp3/" + mp3Info.getLrcName()); LrcProcessor lrcProcessor = new LrcProcessor(); queues = lrcProcessor.process(inputStream); //创建一个UpdateTimeCallback对象 updateTimeCallback = new UpdateTimeCallback(queues); begin = 0 ; currentTimeMill = 0 ; nextTimeMill = 0 ; } catch (FileNotFoundException e) { e.printStackTrace(); } } class BeginButtonListener implements OnClickListener { @Override public void onClick(View v) { //创建一个Intent对象,用于同时Service开始播放MP3 Intent intent = new Intent(); intent.setClass(PlayerActivity.this, PlayerService.class); intent.putExtra("mp3Info", mp3Info); intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG); //读取LRC文件 prepareLrc(mp3Info.getLrcName()); //启动Service startService(intent); //将begin的值置为当前毫秒数 begin = System.currentTimeMillis(); //执行updateTimeCallback handler.postDelayed(updateTimeCallback, 5); isPlaying = true; } } class PauseButtonListener implements OnClickListener { @Override public void onClick(View v) { //通知Service暂停播放MP3 Intent intent = new Intent(); intent.setClass(PlayerActivity.this, PlayerService.class); intent.putExtra("MSG", AppConstant.PlayerMsg.PAUSE_MSG); startService(intent); // if(isPlaying){ handler.removeCallbacks(updateTimeCallback); pauseTimeMills = System.currentTimeMillis(); } else{ handler.postDelayed(updateTimeCallback, 5); begin = System.currentTimeMillis() - pauseTimeMills + begin; } isPlaying = isPlaying ? false : true; } } class StopButtonListener implements OnClickListener { @Override public void onClick(View v) { //通知Service停止播放MP3文件 Intent intent = new Intent(); intent.setClass(PlayerActivity.this, PlayerService.class); intent.putExtra("MSG", AppConstant.PlayerMsg.STOP_MSG); startService(intent); //从Handler当中移除updateTimeCallback handler.removeCallbacks(updateTimeCallback); } } class UpdateTimeCallback implements Runnable{ Queue times = null; Queue messages = null; public UpdateTimeCallback(ArrayList<Queue> queues) { //从ArrayList当中取出相应的对象对象 times = queues.get(0); messages = queues.get(1); } @Override public void run() { //计算偏移量,也就是说从开始播放MP3到现在为止,共消耗了多少时间,以毫秒为单位 long offset = System.currentTimeMillis() - begin; if(currentTimeMill == 0){ nextTimeMill = (Long)times.poll(); message = (String)messages.poll(); } if(offset >= nextTimeMill){ lrcTextView.setText(message); message = (String)messages.poll(); nextTimeMill = (Long)times.poll(); } currentTimeMill = currentTimeMill + 10; handler.postDelayed(updateTimeCallback, 10); } } }
3.PlayerService
package hui.mp3player; import hui.lrc.LrcProcessor; import hui.model.Mp3Info; import hui.mp3player.AppConstant; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.Queue; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.net.Uri; import android.os.Environment; import android.os.IBinder; public class PlayerService extends Service { private boolean isPlaying = false; private boolean isPause = false; private boolean isReleased = false; private MediaPlayer mediaPlayer = null; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Mp3Info mp3Info = (Mp3Info) intent.getSerializableExtra("mp3Info"); int MSG = intent.getIntExtra("MSG", 0); if (mp3Info != null) { if(MSG == AppConstant.PlayerMsg.PLAY_MSG){ play(mp3Info); } } else { if(MSG == AppConstant.PlayerMsg.PAUSE_MSG){ pause(); } else if(MSG == AppConstant.PlayerMsg.STOP_MSG){ stop(); } } return super.onStartCommand(intent, flags, startId); } private void play(Mp3Info mp3Info) { String path = getMp3Path(mp3Info); mediaPlayer = MediaPlayer.create(this, Uri.parse("file://" + path)); mediaPlayer.setLooping(false); mediaPlayer.start(); isPlaying = true; isReleased = false; } private void pause() { if (mediaPlayer != null) { if (!isReleased) { if (!isPause) { mediaPlayer.pause(); isPause = true; isPlaying = true; } else { mediaPlayer.start(); isPause = false; } } } } private void stop() { if (mediaPlayer != null) { if (isPlaying) { if (!isReleased) { mediaPlayer.stop(); mediaPlayer.release(); isReleased = true; } isPlaying = false; } } } private String getMp3Path(Mp3Info mp3Info) { String SDCardRoot = Environment.getExternalStorageDirectory() .getAbsolutePath(); String path = SDCardRoot + File.separator + "mp3" + File.separator + mp3Info.getMp3Name(); return path; } }
上个图------很丑---UI搞得很辛苦所以放弃了,弄下天气的程序