一:什么是ANR
ANR:Application Not Responding,即应用无响应
二:ANR的类型
ANR一般有三种类型:
1:KeyDispatchTimeout(5 seconds) --首要类型
按键或触摸事务在特按时刻内无响应
2:BroadcastTimeout(10 seconds)
BroadcastReceiver在特按时刻内无法处置完成
3:ServiceTimeout(20 seconds) --小概率类型
Service在特定的时刻内无法处置完成
三:KeyDispatchTimeout
Akey or touch event was not dispatched within the specified time(按键或触摸事务在特按时刻内无响应)
具体的超不时刻的界说在framework下的
ActivityManagerService.java
//How long we wait until we timeout on key dispatching.
staticfinal int KEY_DISPATCHING_TIMEOUT = 5*1000
四:为什么会超时呢?
超不时刻的计数一般是从按键分发给app预备。超时的原因一般有两种:
(1)当前的事务没有机缘得处处置(即UI线程正在处置前一个事务,没有及时的完成或者looper被某种原因梗阻住了)
(2)当前的事务正在处置,但没有及时完成
五:若何避免KeyDispatchTimeout
1:UI线程尽量只做跟UI相关的工作
2:耗时的工作(好比数据库操作,I/O,毗连收集或者其它有可能阻碍UI线程的操作)把它放入零丁的线程处置
3:尽量用Handler来处置UIthread和其它thread之间的交互
六:UI线程
说了那么多的UI线程,那么哪些属于UI线程呢?
UI线程首要搜罗如下:
ActivitynCreate(), onResume(), onDestroy(), onKeyDown(), onClick(),etc
AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel,etc
Mainthread handler: handleMessage(), post*(runnable r), etc
other
七:若何去剖析ANR
先看个LOG:
04-01 13:12:11.572 I/InputDispatcher( 220): Application is not responding:Window{2b263310com.android.email/com.android.email.activity.SplitScreenActivitypaused=false}. 5009.8ms since event, 5009.5ms since waitstarted
04-0113:12:11.572 I/WindowManager( 220): Input event dispatching timedout sending tocom.android.email/com.android.email.activity.SplitScreenActivity
04-01 13:12:14.123 I/Process( 220): Sending signal. PID: 21404 SIG: 3---发生ANR的时刻和生成trace.txt的时刻
04-01 13:12:14.123 I/dalvikvm(21404):threadid=4: reacting to signal 3
……
04-0113:12:15.872 E/ActivityManager( 220): ANR in com.android.email(com.android.email/.activity.SplitScreenActivity)
04-0113:12:15.872 E/ActivityManager( 220): Reason:keyDispatchingTimedOut
04-0113:12:15.872 E/ActivityManager( 220): Load: 8.68 / 8.37 / 8.53
04-0113:12:15.872 E/ActivityManager( 220):CPUusage from 4361ms to 699ms ago----CPU在ANR发生前的使用情形
04-0113:12:15.872 E/ActivityManager( 220): 5.5%21404/com.android.email: 1.3% user + 4.1% kernel / faults: 10 minor
04-0113:12:15.872 E/ActivityManager( 220): 4.3%220/system_server: 2.7% user + 1.5% kernel / faults: 11 minor 2 major
04-0113:12:15.872 E/ActivityManager( 220): 0.9%52/spi_qsd.0: 0% user + 0.9% kernel
04-0113:12:15.872 E/ActivityManager( 220): 0.5%65/irq/170-cyttsp-: 0% user + 0.5% kernel
04-0113:12:15.872 E/ActivityManager( 220): 0.5%296/com.android.systemui: 0.5% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 100%TOTAL: 4.8% user + 7.6% kernel + 87% iowait
04-0113:12:15.872 E/ActivityManager( 220):CPUusage from 3697ms to 4223ms later:-- ANR后CPU的使用量
04-0113:12:15.872 E/ActivityManager( 220): 25%21404/com.android.email: 25% user + 0% kernel / faults: 191 minor
04-0113:12:15.872 E/ActivityManager( 220): 16% 21603/__eas(par.hakan: 16% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 7.2% 21406/GC: 7.2% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 1.8% 21409/Compiler: 1.8% user + 0% kernel
04-0113:12:15.872 E/ActivityManager( 220): 5.5%220/system_server: 0% user + 5.5% kernel / faults: 1 minor
04-0113:12:15.872 E/ActivityManager( 220): 5.5% 263/InputDispatcher: 0% user + 5.5% kernel
04-0113:12:15.872 E/ActivityManager( 220): 32%TOTAL: 28% user + 3.7% kernel
从LOG可以看出ANR的类型,CPU的使用情形,若是CPU使用量接近100%,声名当前设备很忙,有可能是CPU饥饿导致了ANR
若是CPU使用量很少,声名主线程被BLOCK了
若是IOwait很高,声名ANR有可能是主线程在进行I/O操作造成的
除了看LOG,解决ANR还得需要trace.txt文件,
若何获取呢?可以用如下号令获取
$chmod 777 /data/anr
$rm /data/anr/traces.txt
$ps
$kill -3PID
adbpull data/anr/traces.txt ./mytraces.txt
从trace.txt文件,看到最多的是如下的信息:
-----pid 21404 at 2011-04-0113:12:14 -----
Cmdline: com.android.email
DALVIK THREADS:
(mutexes: tll=0tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
"main" prio=5 tid=1NATIVE
| group="main" sCount=1 dsCount=0obj=0x2aad2248 self=0xcf70
| sysTid=21404 nice=0 sched=0/0cgrp=[fopen-error:2] handle=1876218976
atandroid.os.MessageQueue.nativePollOnce(Native Method)
atandroid.os.MessageQueue.next(MessageQueue.java:119)
atandroid.os.Looper.loop(Looper.java:110)
at android.app.ActivityThread.main(ActivityThread.java:3688)
at java.lang.reflect.Method.invokeNative(Native Method)
atjava.lang.reflect.Method.invoke(Method.java:507)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
at dalvik.system.NativeStart.main(Native Method)
声名主线程在期待下条新闻进入新闻队列
八:Thread状况
ThreadState (defined at “dalvik/vm/thread.h “)
THREAD_UNDEFINED = -1, /* makes enum compatible with int32_t */
THREAD_ZOMBIE = 0, /* TERMINATED */
THREAD_RUNNING = 1, /* RUNNABLE or running now */
THREAD_TIMED_WAIT = 2, /* TIMED_WAITING in Object.wait() */
THREAD_MONITOR = 3, /* BLOCKED on a monitor */
THREAD_WAIT = 4, /* WAITING in Object.wait() */
THREAD_INITIALIZING= 5, /* allocated, not yet running */
THREAD_STARTING = 6, /* started, not yet on thread list */
THREAD_NATIVE = 7, /* off in a JNI native method */
THREAD_VMWAIT = 8, /* waiting on a VM resource */
THREAD_SUSPENDED = 9, /* suspended, usually by GC or debugger */
九:若何查询拜访并解决ANR
1:首先剖析log
2: 从trace.txt文件查看挪用stack.
3: 看代码
4:细心查看ANR的成因(iowait?block?memoryleak?)
十:案例
案例1:关头词:ContentResolver in AsyncTask onPostExecute, high iowait
Process:com.android.email
Activity:com.android.email/.activity.MessageView
Subject:keyDispatchingTimedOut
CPU usage from 2550ms to -2814ms ago:
5%187/system_server: 3.5% user + 1.4% kernel / faults: 86 minor 20major
4.4% 1134/com.android.email: 0.7% user + 3.7% kernel /faults: 38 minor 19 major
4% 372/com.android.eventstream: 0.7%user + 3.3% kernel / faults: 6 minor
1.1% 272/com.android.phone:0.9% user + 0.1% kernel / faults: 33 minor
0.9%252/com.android.systemui: 0.9% user + 0% kernel
0%409/com.android.eventstream.telephonyplugin: 0% user + 0% kernel /faults: 2 minor
0.1% 632/com.android.devicemonitor: 0.1% user + 0%kernel
100%TOTAL: 6.9% user + 8.2% kernel +84%iowait
-----pid 1134 at 2010-12-17 17:46:51 -----
Cmd line:com.android.email
DALVIK THREADS:
(mutexes: tll=0 tsl=0tscl=0 ghl=0 hwl=0 hwll=0)
"main" prio=5 tid=1 WAIT
|group="main" sCount=1 dsCount=0 obj=0x2aaca180self=0xcf20
| sysTid=1134 nice=0 sched=0/0 cgrp=[fopen-error:2]handle=1876218976
at java.lang.Object.wait(Native Method)
-waiting on <0x2aaca218> (a java.lang.VMThread)
atjava.lang.Thread.parkFor(Thread.java:1424)
atjava.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
atsun.misc.Unsafe.park(Unsafe.java:337)
atjava.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
atjava.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:808)
atjava.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:841)
atjava.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1171)
atjava.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:200)
atjava.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:261)
atandroid.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:378)
atandroid.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:222)
atandroid.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53)
atandroid.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356)
atandroid.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1235)
atandroid.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1189)
atandroid.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1271)
atcom.android.email.provider.EmailProvider.query(EmailProvider.java:1098)
atandroid.content.ContentProvider$Transport.query(ContentProvider.java:187)
atandroid.content.ContentResolver.query(ContentResolver.java:268)
atcom.android.email.provider.EmailContent$Message.restoreMessageWithId(EmailContent.java:648)
atcom.android.email.Controller.setMessageRead(Controller.java:658)
atcom.android.email.activity.MessageView.onMarkAsRead(MessageView.java:700)
atcom.android.email.activity.MessageView.access$2500(MessageView.java:98)
atcom.android.email.activity.MessageView$LoadBodyTask.onPostExecute(MessageView.java:1290)
atcom.android.email.activity.MessageView$LoadBodyTask.onPostExecute(MessageView.java:1255)
atandroid.os.AsyncTask.finish(AsyncTask.java:417)
atandroid.os.AsyncTask.access$300(AsyncTask.java:127)
atandroid.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
atandroid.os.Handler.dispatchMessage(Handler.java:99)
atandroid.os.Looper.loop(Looper.java:123)
atandroid.app.ActivityThread.main(ActivityThread.java:3652)
atjava.lang.reflect.Method.invokeNative(Native Method)
atjava.lang.reflect.Method.invoke(Method.java:507)
atcom.android.internal.os.ZygoteIn
原因:IOWait很高,声名当前系统在忙于I/O,是以数据库操作被梗阻
原本:
finalMessagemessage=Message.restoreMessageWithId(mProviderContext,messageId);
if(message==null){
return;
}
Accountaccount=Account.restoreAccountWithId(mProviderContext,message.mAccountKey);
if(account==null){
return;//isMessagingController returns false for null, but let's make itclear.
}
if(isMessagingController(account)){
new Thread(){
@Override
public void run(){
mLegacyController.processPendingActions(message.mAccountKey);
}
}.start();
}
解决后:
newThread() {
finalMessagemessage=Message.restoreMessageWithId(mProviderContext,messageId);
if(message==null){
return;
}
Accountaccount=Account.restoreAccountWithId(mProviderContext,message.mAccountKey);
if(account==null){
return;//isMessagingController returns false for null, but let's make itclear.
}
if(isMessagingController(account)) {
mLegacyController.processPendingActions(message.mAccountKey);
}
}.start();
关于AsyncTask:http://developer.android.com/reference/android/os/AsyncTask.html
案例2:关头词:在UI线程进行收集数据的读写
ANRin process: com.android.mediascapehotoViewer (last incom.android.mediascapehotoViewer)
Annotation:keyDispatchingTimedOut
CPU usage:
Load: 6.74 / 6.89 / 6.12
CPUusage from 8254ms to 3224ms ago:
ovider.webmedia: 4% = 4% user +0% kernel / faults: 68 minor
system_server: 2% = 1% user + 0%kernel / faults: 18 minor
re-initialized>: 0% = 0% user + 0%kernel / faults: 50 minor
events/0: 0% = 0% user + 0%kernel
TOTAL:7% = 6% user + 1% kernel
DALVIKTHREADS:
""main"" prio=5 tid=3 NATIVE
|group=""main"" sCount=1 dsCount=0 s=Yobj=0x4001b240 self=0xbda8
| sysTid=2579 nice=0 sched=0/0cgrp=unknown handle=-1343993184
atorg.apache.harmony.luni.platform.OSNetworkSystem.receiveStreamImpl(NativeMethod)
atorg.apache.harmony.luni.platform.OSNetworkSystem.receiveStream(OSNetworkSystem.java:478)
atorg.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:565)
atorg.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:87)
atorg.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection$LimitedInputStream.read(HttpURLConnection.java:303)
atjava.io.InputStream.read(InputStream.java:133)
atjava.io.BufferedInputStream.fillbuf(BufferedInputStream.java:157)
atjava.io.BufferedInputStream.read(BufferedInputStream.java:346)
atandroid.graphics.BitmapFactory.nativeDecodeStream(Native Method)
atandroid.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459)
atcom.android.mediascape.activity.PhotoViewerActivity.getPreviewImage(PhotoViewerActivity.java:4465)
atcom.android.mediascape.activity.PhotoViewerActivity.dispPreview(PhotoViewerActivity.java:4406)
atcom.android.mediascape.activity.PhotoViewerActivity.access$6500(PhotoViewerActivity.java:125)
atcom.android.mediascape.activity.PhotoViewerActivity$33$1.run(PhotoViewerActivity.java:4558)
atandroid.os.Handler.handleCallback(Handler.java:587)
atandroid.os.Handler.dispatchMessage(Handler.java:92)
atandroid.os.Looper.loop(Looper.java:123)
atandroid.app.ActivityThread.main(ActivityThread.java:4370)
atjava.lang.reflect.Method.invokeNative(Native Method)
atjava.lang.reflect.Method.invoke(Method.java:521)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
atdalvik.system.NativeStart.main(Native Method)
关于收集毗连,在设计的时辰可以设置个timeout的时刻或者放入自力的线程来处置。
关于Handler的问题,可以参考:http://developer.android.com/reference/android/os/Handler.html
案例3:
关头词:Memoryleak/Thread leak
11-1621:41:42.560 I/ActivityManager( 1190): ANR in process:android.process.acore (last in android.process.acore)
11-1621:41:42.560 I/ActivityManager( 1190): Annotation:keyDispatchingTimedOut
11-16 21:41:42.560 I/ActivityManager(1190): CPU usage:
11-16 21:41:42.560 I/ActivityManager( 1190)oad: 11.5 / 11.1 / 11.09
11-16 21:41:42.560 I/ActivityManager(1190): CPU usage from 9046ms to 4018ms ago:
11-16 21:41:42.560I/ActivityManager( 1190): d.process.acore:98%= 97% user + 0% kernel / faults: 1134 minor
11-16 21:41:42.560I/ActivityManager( 1190): system_server: 0% = 0% user + 0% kernel /faults: 1 minor
11-16 21:41:42.560 I/ActivityManager( 1190): adbd:0% = 0% user + 0% kernel
11-16 21:41:42.560 I/ActivityManager(1190): logcat: 0% = 0% user + 0% kernel
11-16 21:41:42.560I/ActivityManager( 1190): TOTAL:100% = 98% user + 1% kernel
Cmdline: android.process.acore
DALVIK THREADS:
"main"prio=5 tid=3 VMWAIT
|group="main" sCount=1 dsCount=0 s=N obj=0x40026240self=0xbda8
| sysTid=1815 nice=0 sched=0/0 cgrp=unknownhandle=-1344001376
atdalvik.system.VMRuntime.trackExternalAllocation(NativeMethod)
atandroid.graphics.Bitmap.nativeCreate(Native Method)
atandroid.graphics.Bitmap.createBitmap(Bitmap.java:468)
atandroid.view.View.buildDrawingCache(View.java:6324)
atandroid.view.View.getDrawingCache(View.java:6178)
atandroid.view.ViewGroup.drawChild(ViewGroup.java:1541)
……
atcom.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
atandroid.view.ViewRoot.draw(ViewRoot.java:1349)
atandroid.view.ViewRoot.performTraversals(ViewRoot.java:1114)
atandroid.view.ViewRoot.handleMessage(ViewRoot.java:1633)
atandroid.os.Handler.dispatchMessage(Handler.java:99)
atandroid.os.Looper.loop(Looper.java:123)
atandroid.app.ActivityThread.main(ActivityThread.java:4370)
atjava.lang.reflect.Method.invokeNative(Native Method)
atjava.lang.reflect.Method.invoke(Method.java:521)
atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
atdalvik.system.NativeStart.main(Native Method)
"Thread-408"prio=5 tid=329 WAIT
|group="main" sCount=1 dsCount=0 s=N obj=0x46910d40self=0xcd0548
| sysTid=10602 nice=0 sched=0/0 cgrp=unknownhandle=15470792
at java.lang.Object.wait(Native Method)
-waiting on <0x468cd420> (a java.lang.Object)
atjava.lang.Object.wait(Object.java:288)
atcom.android.dialer.CallLogContentHelper$UiUpdaterExecutor$1.run(CallLogContentHelper.java:289)
atjava.lang.Thread.run(Thread.java:1096)
剖析:
atdalvik.system.VMRuntime.trackExternalAllocation(NativeMethod)内存不足导致block在建树bitmap上
**MEMINFO in pid 1360 [android.process.acore] **
native dalvik other total
size: 17036 23111 N/A 40147
allocated: 16484 20675 N/A 37159
free: 296 2436 N/A 2732
解决:若是机子的内存族,可以改削虚拟机的内存为36M或更大,可是最好是复查代码,查看哪些内存没有释放
原文:http://www.ce91.com/thread-83374-1-1.html
iphone 2009-09-14 14:31:30 阅读463 评论1
字号:大中小
为什么要用deb?原因主要有以下几点:
安装和卸载都还算方便;
可以获得最大权限(相比IPA而言),能进行系统层面的操作;
一些破解软件,尤其是涉及系统层面的,需要手动传文件改属性等,而deb安装可以一次搞定;
deb安装的程序图标上不会出现叉叉。本帖包含以下内容:
一、deb的安装:
1. Cydia上下载安装
2. 利用Cydia的AutoInstall安装
3. 在iPhone/iPod Touch上用MobileTerminal安装
4. 在电脑上以控制台(WinSCP自带)安装
二、 deb的制作
1. deb文件的下载
2. 解包deb文件并提取安装控制信息
3. 编辑、修改、集成、自定义安装信息(破解、汉化、美化等)
4. 打包deb
5. 将某些复杂的pxl(不是只有一个主程序)转换成deb
三、问题及解答
说明:本帖里的引用(quote)只是为了区别而设,并无实际引用。而代码(code)倒是真的可以直接复制
以下是安装部分
方法一: 在Cydia中直接下载安装
引用
此条纯属废话
方法二: 利用Cydia自带的自动安装功能安装
引用
随便用什么软件(WinSCP,iBrickr,91,TotalCommander等)将要安装的deb文件上传到/private/var/root/Media/Cydia/AutoInstall/目录下。默认情况下是没有Media目录的,因此要手动建立Media、Cydia和AutoInstall三个目录(大小写要匹配)。(都不需要设置属性。除WinSCP外,其余都不需要装有OpenSSH)
上传完之后重启(不是Respring)iPhone,进Cydia就可以看到程序已经安装上去了。
AutoInstall的好处是,不需要手动清理deb安装文件,也不需要输入命令代码。
因为iBrickr,91,TotalCommander等软件连接iPhone不需要SSH协议,故可以用此方法来安装OpenSSH。
问题:1.有时候这种方法安装不了,可能是因为要安装的程序需要先安装有另外一个程序,在没有安装的情况下,该安装就会失败。当然还有一个不能安装的问题,具体我也不清楚是怎么回事,目前也没解决办法。
2.安装之后没图标怎么办?尝试用CacheDel清理缓存,或者用91修复图标,或者删除/private/var/mobile/Library/Caches目录下的com.apple.mobile.installation.plist,然后respring。
方法三: 利用iPhone/iPod Touch上的软件MobileTerminal安装
引用
先把要安装的deb传到iPhone任意一个目录下
然后运行MobileTerminal
输入 su 回车
提示Password,接着输入alpine,回车
用cd命令定位到deb所在文件夹,比如deb文件夹在var/mobile/Documents目录下,则输入cd var/mobile/Documents
可以先用ls命令查看deb文件是否存在,命令就是ls加回车(此步非必须)
输入dpkg -i XXX.deb 比如说要安装的是Openssh.deb,那么就输入dpkg -i Openssh.deb,大小写要完全匹配
如果要安装的比较多,或是嫌输入文件名太麻烦,可以直接输入dpkg -i *.deb以安装该目录下的全部deb文件
安装完成之后一般是出现Setting up XXXXX字样,出现该字样即表示安装结束,可以退出了
Respring或者重启就OK了
卸载deb, Cydia上直接卸载就不说了。命令行卸载的话,输入dpkg -r XXXX (具体操作见后面的图文教程)
好处:命令行安装的deb不会出现AutoInstall那样安装失败的情况,除非deb包本身有问题。安装完后一般也不会出现没有图标的问题。
另外就是,在命令行里可以建立某些特殊的快捷方式,也可以直接在手机上更改文件属性等系统级操作。
缺点:输入比较麻烦,需要安装有MobileTerminal软件。
有WiFi的话直接在Cydia上就可以装,没有的话可以按第二种方法先安装MobileTerminal,再进行其它操作
方法四: 用控制台安装
引用
首先确保iPhone/iPod Touch上已安装有OpenSSH,且处于开启状态。
打开WinSCP,连接上设备。(用WiFi或者数据线版都行)
将要安装的deb文件传送到iPhone/Ipod Touch上,目录随意,传完之后不要更改目录。
退出Cydia,MobileTerminal等程序(不是删除),否则无法用控制台安装
打开命令行(控制台),输入dpkg -i XXXX.deb以安装单个程序,或者输入dpkg -i *.deb以安装当前目录下的全部deb文件。
卸载deb, Cydia上直接卸载就不说了。命令行卸载的话,输入dpkg -r XXXX (具体操作见后面的图文教程)
优点:操作方便,只要拖过去然后一个dpkg -i *.deb就可以搞定大量deb的安装。
缺点:必须要用WinSCP,手机上也必须安装有OpenSSH
总体上来说,个人认为这种方法是最简单,最高效的,因为全部要输入的命令也就只有dpkg -i一句。
下面是如何在刚破解完的手机上离线安装OpenSSH和MobileTerminal,以及如何使用MobileTerminal和控制台以命令行安装deb。
引用
1. 先下载iBrickr,解压缩之后运行ibrickr.exe (记得先插上数据线)
下载 iBrickr 0.91 ibrickr_v0.91.rar (4709 K) 下载次数:338
2.点击Files以上传文件
3.在右边的逐次点击文件夹以进入/private/var/root/
注意,不能直接点var。因为根目录的var实际上是一个快捷方式,在ibrickr中会被当作文件
4. 进入到root目录,应该只有Library一个目录(截图里的.bash_history我不知道哪来的)
5. 创建需要的文件夹。点Create folder以创建,可以依次创建Media、Cydia和AutoInstall三个文件夹,也可以一次性输入Media/Cydia/AutoInstall以创建3个目录
6. 选中要上传的deb文件,可以只选一个,也可以拖到选择或者用Shift或Ctrl进行多选
MobileTerminal.deb (279 K) 下载次数:112 ssl.deb (2786 K) 下载次数:80 ssh.deb (778 K) 下载次数:91
7. 文件上传中,不要关闭程序,也不要断开连接
8. 上传成功
9. 重启设备,重启之后就可以看到程序已经安装完毕了。没有图标的请参照上面说的来修正
下面是在手机上用MobileTerminal来安装deb
引用
1. 将要安装的deb传到手机里,此处以var/mobile/Documents为例
2. 打开MobileTerminal,输入su,会提示你密码,继续输入alpine(密码不会显示的)
成功以后会显示localhost: /var/mobile root# (MobileTerminal默认的打开目录就是mobile)
3. (非必要)可以输入ls命令以查看文件夹下有什么内容。在DOS中相同的命令就是dir
4. 进入Documents。 输入cd Documents,可以看到路径已经是Documents了。图省事的话可以直接将文件传到mobile目录下,则此步可跳过
5. (非必要)继续用ls命令查看deb是否已正确传输
6. 单独安装一个deb。以安装clippy为例(安装直接最好把文件名改短一点,免得输入起来麻烦)
输入 dpkg -i clippy.deb
7. 批量安装。输入 dpkg -i *.deb
8. 安装结束,出现Setting up XXX字样
9. 重启或Respring iPhone,桌面即可看到程序图标(没有图标的除外,像SBSettings等,安装成功没有可以进Cydia里查看)
10. 卸载安装过的deb。 命令行中输入dpkg -r 程序名。安装的时候Setting up XXXX这个就是程序名。
例如mobilelog安装的时候是Setting up com.xsellize.mobilelog (2.2)...,那么卸载的时候就应该输入 dpkg -r com.xsellize.mobilelog
11. 记得清理deb安装文件。命令行安装不会自动删除已安装的deb,AutoInstall才会自动删除。
最后是用控制台安装
引用
1. 连接上设备之后,将要安装的deb用WinSCP传到设备上
下载:WinSCP无WiFi绿色版 WinSCP.rar (2645 K) 下载次数:200
2. 打开命令行(控制台),也可以按Ctrl + T 快捷键
3. 命令行已连接(控制台)
4. 输入dpkg -i XXXX.deb 或dpkg -i *.deb以安装,出现Setting up XXXX字样即表示安装结束(Setting up后的文字还有用,可以记下来)
5. 控制台会自动记录每一次输入的命令以方便下次调用
6. 输入dpkg -r XXXX以卸载,这里XXXX就是之前安装时Setting up后出现的mobileterminal
安装部分完
以下是制作deb部分
提示:deb下载部分和程序文件修改可以在Windows下或者Linux下完成,但deb的解包和打包则必须在Linux系统下完成。
不是所有的Linux系统都支持对deb的编辑,只有安装了dpkg的系统才可以编辑修改deb文件。DEBIAN和Ubuntu是可以的,Fedora因为默认没有dpkg,所以无法修改(应该可以安装dpkg)。
理论上来说在iPhone上可以用MobileTerminal制作deb,但我一直没成功过,在打包的时候就会出错。用控制台都不行,会直接导致连接断开。
制作deb我是在Ubuntu下完成的。
首先是要获取制作deb的素材,如果是修改已有的deb,那么需要先下载到deb文件。
Cydia上的deb下载有人发过,这里我再赘述一下,如果是直接从文件新建立deb,如CacheDel,可以略过下载部分和解包部分。
获取deb的url地址: Cydia上的软件可以去http://www.modmyi.com/cydia/搜索,软件简介里的的File Name 即使deb的文件名。前面加上源的地址就OK了。
此处以制作iBluetooth汉化破解版为例。
搜索iBluetooth的文件名,发现是.//deb/com.medevil.ibluetooth_1.0_iphoneos-arm.deb
而iBluetooth是在iSpazio这个源里面,源地址在Cydia中可以直接看到,是http://www.ispaziorepo.com/cydia/apt/
那么iBluetooth的绝对下载路径就是http://www.ispaziorepo.com/cydia ... .0_iphoneos-arm.deb
对于Modmyi上查不到的源,可以打开/var/lib/apt/lists/下打开._Packages来查看文件名,下载方式仍是源地址+文件名。
得到需要的deb之后,下一步就是解包了。
引用
1. 准备好要制作的deb的文件,这里我在桌面上建立了个文件夹deb,子文件夹temp,将原始deb文件放在deb文件夹下(一次只能放一个,否则解包或者之后的打包过程会出问题)。
2. 启动Terminal(命令行/终端)
3. 进入原始deb所在的文件夹,命令 cd。此处是 cd Desktop/deb/(注意大小写)
4. 输入 dpkg-deb -x ./*.deb ./temp 以解包主程序文件
temp下出现文件夹Applications
5. 输入 dpkg-deb -e ./*.deb ./temp/DEBIAN 以解包安装控制脚本
解包完后多出个DEBIAN目录,里面至少有一个control文件,有的还会有postinst,都没有后缀名
6. 以上两步解包要是没问题的话Terminal里是没有显示的,否则会报错。
下面是编辑修改(集成破解补丁,汉化包等)
引用
1. 解包完后,或者是新创建的app,在文件夹中放好之后,将要替换或增加的文件复制到对应目录下。
一般汉化文件XXX.strings,有的是连带文件夹zh_CN.lproj,一起复制进temp/Applications/XXXX.app/目录下
其他需要替换的XXXX.app目录下的文件也是一样操作
如果有些文件不是在XXXX.app目录下,比如说,有的文件是要放在/Library/MobileSubstrate/DynamicLibraries/下,那么就在temp目录下依次新建以上文件夹,并把要用的文件复制进去。(注意大小写要完全一致)
放在其它文件夹下也是类似,但要注意,像WinterBoard的主题文件是放在/var/stash/Themes.XXXXXX/文件夹下的,在制作的时候就只用建/var/stash/Themes/,不要后面那一串乱码
2. 单独编辑文件(主要是语言包)。我测试的结果是,plist文件在Ubuntu下可以直接用gedit文本编辑器打开修改,而strings文件则无法打开,只能在Windows下用Pedit打开。图片文件有的(有预览的)可以直接修改,有的(无预览的)需要在Windows下用 windowsfixpng转换之后才能修改。
要注意的是,在Ubuntu(其它Linux下是否一样我不知道)下编辑文件,会自动将旧文件保存为XXXX.XXX~文件,且是隐藏属性。按Ctrl + H 以显示隐藏文件,如图
记得删掉多余的文件
3. 修改属性。 有些文件或文件夹要求有664,775等属性,而DEBIAN文件夹(安装控制脚本)则必须要755属性,有两种修改方式。
一是在Terminal里用chmod命令修改,另一个则是以图形界面设置属性。
iBluetooth的破解补丁替换原文件以后要设属性为7777,那么可以在Terminal里输入 chmod -R 7777 ./temp/Applications/iBluetooth.app/iBluetooth_ 成功的话没有提示,否则会报错
或直接在该文件/文件夹上右键-属性-权限,将三个访问全部设为读写(7),并勾选 执行(第一个7,不勾选就是0),这样就等于将属性设为7777了。
每一位上的数字具体对应什么我还没弄清楚,希望有人能告诉我,谢谢!
chmod -R 755 ./temp/* 是将temp目录下的所有文件夹和文件属性设为755,当然也可以写0755,完全等效。 如果仅仅只是修改一个文件夹属性,则输入 chmod -R 755 ./temp/Applications诸如此类。
当然也可以单独设定某个文件的属性,写明绝对地址就可以了。
最重要的是,要将DEBIAN文件夹设为755属性,命令是chmod -R 755 ./temp/DEBIAN/* 和 chmod -R 755 ./temp/DEBIAN,否则最后生成的deb会不能安装
4. 定义安装脚本。
可以手动修改control文件,显示的是Cydia里的软件信息。但修改过就无法在Cydia中更新了。没有修改的话,当Cydia中出了新的版本就会提示更新。
而有些deb自带preinst或postinst文件,分别是控制在安装deb之前和之后执行一些命令
在preinst中,有的会有remove信息,即指在安装之前先写在旧版本。这里提供iBluetooth的postinst文件以作参考#!/bin/bash
if [[ $1 == configure ]]
then
chown -R 0:0 /Applications/iBluetooth.app/
chmod -R 644 /Applications/iBluetooth.app/
chmod 755 /Applications/iBluetooth.app
chmod 755 /Applications/iBluetooth.app/iBluetooth
chmod 7777 /Applications/iBluetooth.app/iBluetooth_
fi简单来说就是在安装完之后更改某些文件和文件夹的属性。
安装脚本具体怎么配置我也不清楚,盼高人指教。
修改完之后,最后就是打包了
引用
打包其实很简单,一句命令就搞定。dpkg-deb -b ./temp iBluetooth_1.0_CN_Cracked.deb./temp是要打包的文件所存放的位置,iBluetooth_1.0_CN_Cracked.deb是生成的deb的文件名,以上两个根据自己的情况修改。
出现警告很正常,忽略之。
生成的deb
将pxl转换成deb
引用
通常91上的软件大多都有ipa版或deb版,转换的必要性不是很大,就算要转,一般也只是将.app文件重新打包然后自己写个安装信息文件control 就可以了,但对于像熊猫空间和熊猫阅读器这些包含安装控制信息的pxl软件要转又该如何?下面以PandaReader熊猫阅读器为例。
1. 先解包pxl文件,WinRAR,7-zip什么的随便,Linux下也可以用zip命令解压。
2. 解包得到的至少会有XXXX.app的主程序文件,以及一个PxlPkg.plist的配置文件。有的还会多一些用处不明的文件,例如熊猫空间解包之后就是这些(截图是在Windows下,打包还是得到Linux下):
可以看到多了个images文件夹,还有一个readme.htm,一个version.ini。
我自己并不知道这些文件有什么用,也不需要知道有什么具体用处(要修改软件除外),但需要知道这些软件在安装后有什么用,也就是该安到哪里,设为什么属性等等。
而以上这些信息在PxlPkg.plist里可以查到。
3. 在Linux下,将主程序XXX.app,此处是PandaReader.app传到temp/Applications/目录下(没有就新建),然后在 temp目录下创建DEBIAN文件夹,在文件夹里面创建一个空的文本文档control(也可以直接修改其它deb的control文件,这样更省事)
4. control里的信息的写法可以根据PxlPkg.plist里的来写,比如control里的name就是PxlPkg.plist中 CFBundleIdentifier下string的内容,例如此处是NetDragon.Mobile.iPhone.PandaReader;程序安装目录就自己改了;版本号在PxlPkg.plist中是RDPxlPackageVersion下的string,注意control里的版本号不能有空格;图标路径也是根据需要来改。其它的Description之类的自己随便填。
5. 配置安装控制脚本,此处介绍如何将PkgScript文件夹下的Postflight转换为postinst.
打开Postfight文件,可以看到命令如下
chown -R mobile /var/mobile/Library/Preferences/PandaReader
chown -R mobile /var/mobile/Media/EBooks
chmod -R 777 /var/mobile/Media/EBooks
其余的是注释语句,无实际用途,可忽略。
那么在postinst文件里就应该写#!/bin/bash
if [[ $1 == configure ]]
then
chown -R mobile /var/mobile/Library/Preferences/PandaReader
chown -R mobile /var/mobile/Media/EBooks
chmod -R 777 /var/mobile/Media/EBooks
fi这样就写完了postinst文件(此文件用途是在安装完之后创建目录、更改属性等)
6. 最后是怎么知道images,readme.htm,version.ini应该放到哪里。
查看PxlPkg.plist,发现如下语句<dict>
<key>destination</key>
<string>/var/mobile/Media/EBooks/images</string>
<key>overwrite</key>
<true />
<key>permanent</key>
<false />
<key>source</key>
<string>images</string>
</dict>
<dict>
<key>destination</key>
<string>/var/mobile/Media/EBooks/readme.htm</string>
<key>overwrite</key>
<true />
<key>permanent</key>
<false />
<key>source</key>
<string>readme.htm</string>
</dict>
<dict>
<key>destination</key>
<string>/var/mobile/Library/Preferences/PandaReader/version.ini</string>
<key>overwrite</key>
<true />
<key>permanent</key>
<false />
<key>source</key>
<string>version.ini</string>
</dict>这就表示,images文件夹和readme.htm放到/var/mobile/Media/EBooks/下,version.ini放到/var/mobile/Library/Preferences/PandaReader/下。
依次建立以上文件夹并将文件放到合适位置即可。
然后又发现了如下语句 <array>
<string>chmod</string>
<string>-R</string>
<string>755</string>
<string>/var/mobile/Media/EBooks/images</string>
</array>可知images文件夹应设属性755,设属性操作则不再赘述。
7. 完成以上各步之后即可以打包了。
一些问题及解答
引用
1. 为什么解包的文件要解包到temp文件夹下,为什么不能跟原始deb放在同一目录?
答:因为这样在打包的时候会把原始deb一起打包进去。就算是在打包之前删除掉了原始的deb,在打包过程中,由于新的deb已经生成,且在程序目录下,最后打包结束的时候也会包括这个新的deb,显然这不是我们需要的。
2. DEBIAN文件夹一定是要这个名字么?换个名字或者改大小写会有影响么?
答:我对Linux系统也不是特别了解,根据我之前试验的结果,DEBIAN大小写是无所谓的,但一定要这个名字。
3. deb包可以用7-zip打开,那能否用7-zip打包?
答:可以用7-zip解包程序文件,但不能提取出安装脚本,因此无法用7-zip打包。但若是只替换文件,也许可以,我没尝试过。
4. Windows下能否制作deb?
答:Windows下用虚拟机装Linux是肯定可以的,似乎也有在Windows下虚拟Linux的软件,不过我不知道是什么软件。制作deb的关键还是要有dpkg这个程序,否则无法制作deb。
5. iPhone/iPod Touch上该如何制作deb?
答:安装MobileTerminal后即可制作,操作过程同Linux下的,唯一要注意的是先通过电脑把要制作deb的源文件传到设备上,因为iPhone/iPod Touch不能下载,也没解压缩软件。
我在iPhone上试过,不过因为CPU占用率过高而卡死。也许做些小型的deb还可以,大了的就会出问题。
6. Linux下如何制作PXL?
答:制作pxl主要的问题还是属性,其本质只是一个zip包。配置文件修改好之后在Linux下把属性改了再打包就可以了。
RGB颜色查询对照表_files