说明
家里买了个康佳的LED47R5200PDE的Android电视,反应各种慢,操作各种不流畅。太郁闷了,感觉完全是被康佳和京东给坑了。打电话各种反应,结果是各种不理睬。特别是康佳,严重鄙视之。最让人讨厌的是每次开机都要进入Android主页,而不是直接播放电视。心中那个郁闷啊。这让开机时需要两个遥控器操作。
算了,求人不如求己,我自己写个开机自动播放电视的应用。
反编译分析
2013-12-15更新,下载地址在文件最后,
话不多说,下面开始。
==========================================================================================================
下载一个launch,反编译之。
1、首先查看AndroidManifest.xml文件,找到
<activity android:theme="@style/Theme" android:name="com.cyanogenmod.trebuchet.Launcher" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:launchMode="singleTask" android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
</intent-filter>
</activity>
2、使用UltraEdit查看com.cyanogenmod.trebuchet.Launcher的代码(Launcher.smali),呼出函数列表,找到:
.method private startTVSystem()V
.locals 7
.prologue
.line 884
const-string v4, "activity"
invoke-virtual {p0, v4}, Lcom/cyanogenmod/trebuchet/Launcher;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
move-result-object v0
check-cast v0, Landroid/app/ActivityManager;
.line 885
.local v0, am:Landroid/app/ActivityManager;
const/4 v4, 0x2
invoke-virtual {v0, v4}, Landroid/app/ActivityManager;->getRunningTasks(I)Ljava/util/List;
move-result-object v4
const/4 v5, 0x0
invoke-interface {v4, v5}, Ljava/util/List;->get(I)Ljava/lang/Object;
move-result-object v4
check-cast v4, Landroid/app/ActivityManager$RunningTaskInfo;
iget-object v1, v4, Landroid/app/ActivityManager$RunningTaskInfo;->topActivity:Landroid/content/ComponentName;
.line 886
.local v1, cn:Landroid/content/ComponentName;
const-string v4, "Launcher"
new-instance v5, Ljava/lang/StringBuilder;
const-string v6, "the top activity=========="
invoke-direct {v5, v6}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
invoke-virtual {v1}, Landroid/content/ComponentName;->getPackageName()Ljava/lang/String;
move-result-object v6
invoke-virtual {v5, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v5
invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v5
invoke-static {v4, v5}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
.line 887
invoke-virtual {v1}, Landroid/content/ComponentName;->getPackageName()Ljava/lang/String;
move-result-object v4
const-string v5, "com.konka.tvsettings"
invoke-virtual {v4, v5}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v4
if-eqz v4, :cond_0
.line 888
const-string v4, "Launcher"
const-string v5, "the TV app is already on the top task list"
invoke-static {v4, v5}, Landroid/util/Log;->w(Ljava/lang/String;Ljava/lang/String;)I
.line 904
:goto_0
return-void
.line 891
:cond_0
invoke-virtual {v1}, Landroid/content/ComponentName;->getPackageName()Ljava/lang/String;
move-result-object v4
const-string v5, "com.konka.avenger"
invoke-virtual {v4, v5}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v4
if-eqz v4, :cond_1
.line 892
invoke-virtual {p0}, Lcom/cyanogenmod/trebuchet/Launcher;->closeTVWindow()V
.line 894
const-wide/16 v4, 0x3e8
:try_start_0
invoke-static {v4, v5}, Ljava/lang/Thread;->sleep(J)V
:try_end_0
.catch Ljava/lang/InterruptedException; {:try_start_0 .. :try_end_0} :catch_0
.line 900
:cond_1
:goto_1
new-instance v3, Landroid/content/Intent;
const-string v4, "com.konka.tvsettings.intent.action.RootActivity"
invoke-direct {v3, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
.line 901
.local v3, intentActivity:Landroid/content/Intent;
const/high16 v4, 0x1020
invoke-virtual {v3, v4}, Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
.line 903
invoke-virtual {p0}, Lcom/cyanogenmod/trebuchet/Launcher;->getApplicationContext()Landroid/content/Context;
move-result-object v4
invoke-virtual {v4, v3}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
goto :goto_0
.line 895
.end local v3 #intentActivity:Landroid/content/Intent;
:catch_0
move-exception v2
.line 896
.local v2, e:Ljava/lang/InterruptedException;
invoke-virtual {v2}, Ljava/lang/InterruptedException;->printStackTrace()V
goto :goto_1
.end method
找到:
new-instance v3, Landroid/content/Intent;
const-string v4, "com.konka.tvsettings.intent.action.RootActivity"
invoke-direct {v3, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
.line 901
.local v3, intentActivity:Landroid/content/Intent;
const/high16 v4, 0x1020
invoke-virtual {v3, v4}, Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
.line 903
invoke-virtual {p0}, Lcom/cyanogenmod/trebuchet/Launcher;->getApplicationContext()Landroid/content/Context;
move-result-object v4
invoke-virtual {v4, v3}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
看看这儿:
invoke-direct {v3, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
//看Intent的源码
3439 /**
3440 * Create an intent with a given action. All other fields (data, type,
3441 * class) are null. Note that the action <em>must</em> be in a
3442 * namespace because Intents are used globally in the system -- for
3443 * example the system VIEW action is android.intent.action.VIEW; an
3444 * application's custom action would be something like
3445 * com.google.app.myapp.CUSTOM_ACTION.
3446 *
3447 * @param action The Intent action, such as ACTION_VIEW.
3448 */
3449 public Intent(String action) {
3450 setAction(action);
3451 }
3、把这段代码,用java表示出来,如下所示:
/**
* 启动TV。
*/
public void startTV()
{
//invoke-direct {v3, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
Intent it = new Intent("com.konka.tvsettings.intent.action.RootActivity");
it.addFlags(0x1020);
this.startActivity(it);
}
4、写个APK,测试下。测试代码如下
package com.cnblogs.jevan.autostarttv;
import com.cnblogs.jevan.autoplaytv.R;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* 讨厌每次开机都要点击下遥控器的确认键才能播放电视,所以想自己写个应用程序。让塔开机每次都自动进入电视节目。
* @author jevan
* @version (1.0 at 2013-6-14) 测试接口。
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button)findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startTV();
}
});
}
/**
* 启动TV。
*/
public void startTV()
{
//invoke-direct {v3, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
Intent it = new Intent("com.konka.tvsettings.intent.action.RootActivity");
it.addFlags(0x1020);
this.startActivity(it);
}
@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;
}
}
5、测试OK,效果正常。增加开机自动运行的功能。
迁移了博客,把代码补全,下面是开机自运行代码:
/**
* @author enlangs (http://blog.csdn.net/enlangs)
* @version (1.0 at 2013-6-15) 接受开机完成的消息。
* @version 1.2 at 2013-12-15
*
*/
public class AutoRunBroadcastReceiver extends BroadcastReceiver {
private final static String TAG = AutoRunBroadcastReceiver.class.getSimpleName();
/* (non-Javadoc)
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
@Override
public void onReceive(Context arg0, Intent arg1) {
if(arg1.getAction().equals("android.intent.action.BOOT_COMPLETED"))
{
Log.e(TAG,"=================== onReceive ========================");
try {
Thread.sleep(5000);//等5秒,給系統5秒时间准备硬件。可能5秒都不够。
} catch (InterruptedException e) {
e.printStackTrace();
}
Tools.startTV(arg0);
}
}
}
使用说明:
一定要把应用程序放在/system/app目录下,也就是说,系统必须root,然后使用re文件管理器来移动文件。
下载地址
:http://download.csdn.net/detail/enlangs/6719879
完整源码:
https://github.com/enlangs/AutoStartTV